home *** CD-ROM | disk | FTP | other *** search
/ Giga Games 1 / Giga Games.iso / net / hack / 3_1_3 / sys / mac / macwin.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-07-13  |  66.5 KB  |  3,053 lines

  1. /*    SCCS Id: @(#)macwin.c    3.1    93/07/09          */
  2. /* Copyright (c) Jon W{tte, Hao-Yang Wang, Jonathan Handler 1992. */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. /*
  6.  * macwin.c
  7.  */
  8.  
  9. /*
  10.  * I have to quote X11R5:
  11.  *
  12.  *  "If you think you know what this code is doing, you're probably wrong.
  13.  *   Here be serious and nasty dragons."
  14.  *
  15.  * h+ 92-09-26
  16.  */
  17.  
  18. #include "hack.h"
  19. #include "func_tab.h"
  20. #include "mactty.h"
  21. #include "wintty.h"
  22.  
  23. #include <osutils.h>
  24. #include <dialogs.h>
  25. #include <textedit.h>
  26. #include <menus.h>
  27. #ifndef THINK_C
  28. #include <sysequ.h>
  29. #else
  30. #include <LoMem.h>
  31. #endif
  32. #include <resources.h>
  33. #include <desk.h>
  34. #include <gestaltequ.h>
  35. #include <balloons.h>
  36. #include <toolutils.h>
  37. #include <script.h>
  38. #include <OSEvents.h>
  39. #include <Packages.h>
  40. #include <Sound.h>
  41. #include <DiskInit.h>
  42.  
  43. static short kApplicInFront = 1;
  44.  
  45. NhWindow * theWindows = (NhWindow *) NULL ;
  46.  
  47. extern pascal short tty_environment_changed ( WindowPtr ) ;
  48.  
  49. /*
  50.  * Borrowed from the Mac tty port
  51.  */
  52. extern WindowPtr _mt_window;
  53.  
  54. /*
  55.  * Some useful #defines for the scroll bar width and height
  56.  */
  57. #define        SBARWIDTH    15
  58. #define        SBARHEIGHT    13
  59.  
  60. /*
  61.  * We put a TE on the message window for the "top line" queries.
  62.  * top_line is the TE that holds both the query and the user's
  63.  * response.  The first topl_query_len characters in top_line are
  64.  * the query, the rests are the response.  topl_resp is the valid
  65.  * response to a yn query, while topl_resp[topl_def_idx] is the
  66.  * default response to a yn query.
  67.  */
  68. TEHandle top_line = (TEHandle) nil;
  69. int         topl_query_len;
  70. int         topl_def_idx = -1;
  71. char     topl_resp[10] = "";
  72.  
  73. #define CHAR_ANY '\n'
  74.  
  75. /*
  76.  * inSelect means we have a menu window up for selection or
  77.  * something similar. It makes the window with win number ==
  78.  * inSelect a movable modal (unfortunately without the border)
  79.  * and clicking the close box forces an ESC into the key
  80.  * buffer. Don't forget to set inSelect to WIN_ERR when you're
  81.  * done...
  82.  */
  83. winid inSelect = WIN_ERR ;
  84.  
  85. /*
  86.  * The key queue - contains 0 for unused or an ascii value.
  87.  * When getting keys, take the first value and shift the
  88.  * queue, shifting in a 0.
  89.  */
  90. #define QUEUE_LEN 24
  91. const int keyQueueLen = QUEUE_LEN ;
  92. static int keyQueue [ QUEUE_LEN ] ;
  93.  
  94. Boolean gClickedToMove = 0 ; /* For ObscureCursor */
  95.  
  96. static unsigned long gNextClickRepeat = 0xffffffff ;
  97.  
  98. static Point clicked_pos ;    /* For nh_poskey */
  99. static int clicked_mod ;
  100.  
  101. static Boolean cursor_locked = false ;
  102.  
  103. extern void dprintf ( char * , ... ) ;
  104.  
  105.  
  106. void
  107. lock_mouse_cursor(Boolean new_cursor_locked)
  108. {
  109.     cursor_locked = new_cursor_locked;
  110.     if (new_cursor_locked)
  111.         PostEvent(osEvt, mouseMovedMessage<<24);
  112. }
  113.  
  114.  
  115. /*
  116.  * Add key to input queue, force means flush left and replace if full
  117.  */
  118. void
  119. AddToKeyQueue ( int ch , Boolean force )
  120. {
  121.     int i ;
  122.  
  123.     for ( i = 0 ; i < QUEUE_LEN ; i ++ ) {
  124.  
  125.         if ( ! keyQueue [ i ] ) {
  126.  
  127.             keyQueue [ i ] = ch ;
  128.             return ;
  129.         }
  130.     }
  131.     if ( force ) {
  132.         for ( i = 0 ; i < QUEUE_LEN - 1 ; i ++ ) {
  133.             keyQueue [ i ] = keyQueue [ i + 1 ] ;
  134.         }
  135.         keyQueue [ QUEUE_LEN - 1 ] = ch ;
  136.     }
  137. }
  138.  
  139.  
  140. /*
  141.  * Cursor movement
  142.  */
  143. RgnHandle gMouseRgn = (RgnHandle) NULL ;
  144.  
  145. /*
  146.  * _Gestalt madness - we rely heavily on the _Gestalt glue, since we
  147.  * don't check for the trap...
  148.  */
  149. MacFlags macFlags ;
  150.  
  151. /*
  152.  * The screen layouts on the small 512x342 screen need special cares.
  153.  */
  154. Boolean small_screen;
  155.  
  156. /*
  157.  * Async flag for keeping track of scrollbars...
  158.  * Used by InvalScrollBar ( )
  159.  */
  160. static NhWindow * asyDSC = (NhWindow *) NULL ;
  161.  
  162. /*
  163.  * The font to be used in the text window
  164.  */
  165. short text_wind_font = geneva;
  166.  
  167. /*
  168.  * Whether to adjust the height of a text window according to its contents
  169.  */
  170. boolean full_screen = FALSE;
  171.  
  172. char macPad = 1 ;
  173.  
  174. Handle mBar ;
  175. MenuHandle appleMenu ;
  176. MenuHandle fileMenu ;
  177. MenuHandle editMenu ;
  178. MenuHandle actionMenu ;
  179. MenuHandle inventoryMenu ;
  180. MenuHandle thingsMenu ;
  181. MenuHandle extendedMenu ;
  182. MenuHandle infoMenu ;
  183. MenuHandle helpMenu ;
  184.  
  185. #ifdef NHW_BASE
  186. # undef NHW_BASE
  187. #endif
  188. #define NHW_BASE 0
  189. extern winid BASE_WINDOW ; // Was: , WIN_MAP , WIN_MESSAGE , WIN_INVEN , WIN_STATUS ;
  190.  
  191. void NDECL(port_help);
  192.  
  193. int NDECL(SanePositions);
  194. Boolean FDECL(RetrieveWinPos, (WindowPtr,short *,short *));
  195. void NDECL ( InitMac ) ;
  196. void NDECL(InitRes);
  197. void FDECL(GeneralKey, ( EventRecord * theEvent , WindowPtr theWindow ));
  198. void FDECL(HandleKey, ( EventRecord * theEvent ));
  199. void FDECL(HandleClick, ( EventRecord * theEvent ));
  200. void FDECL(HandleUpdate, ( EventRecord * theEvent ));
  201. void FDECL(HandleEvent, ( EventRecord * theEvent ));
  202. void FDECL(WindowGoAway, ( EventRecord *, WindowPtr));
  203. void NDECL(DimMenuBar);
  204. void NDECL(UndimMenuBar);
  205. int FDECL(filter_scroll_key,(const int, NhWindow *));
  206.  
  207. void SetFrameItem ( DialogPtr , short , short ) ;
  208. void FlashButton ( DialogPtr , short ) ;
  209.  
  210. void trans_num_keys ( EventRecord * ) ;
  211.  
  212. #ifndef THINK_C
  213. /*
  214.  * Why aren't these declared when including hack.h - I thought
  215.  * they were...
  216.  */
  217. void FDECL(putsym, ( winid win , int x , int y , CHAR_P sym ));
  218. #endif
  219.  
  220. #define NUM_FUNCS 6
  221. static void FDECL(macKeyNull, ( EventRecord * , WindowPtr )) ;
  222. static void FDECL(macKeyMessage, ( EventRecord * , WindowPtr )) ;
  223. static void FDECL(macKeyTerm, ( EventRecord * , WindowPtr )) ;
  224. static void FDECL(macKeyMenu, ( EventRecord * , WindowPtr )) ;
  225. static void FDECL(macKeyText, ( EventRecord * , WindowPtr )) ;
  226.  
  227. static void FDECL(macClickNull, ( EventRecord * , WindowPtr )) ;
  228. static void FDECL(macClickMessage, ( EventRecord * , WindowPtr )) ;
  229. static void FDECL(macClickTerm, ( EventRecord * , WindowPtr )) ;
  230. static void FDECL(macClickMenu, ( EventRecord * , WindowPtr )) ;
  231. static void FDECL(macClickText, ( EventRecord * , WindowPtr )) ;
  232.  
  233. static void FDECL(macUpdateNull, ( EventRecord * , WindowPtr )) ;
  234. static void FDECL(macUpdateMessage, ( EventRecord * , WindowPtr )) ;
  235. static void FDECL(macUpdateTerm, ( EventRecord * , WindowPtr )) ;
  236. static void FDECL(macUpdateMenu, ( EventRecord * , WindowPtr )) ;
  237. static void FDECL(macUpdateText, ( EventRecord * , WindowPtr )) ;
  238.  
  239. static void FDECL(macCursorNull, ( EventRecord * , WindowPtr , RgnHandle )) ;
  240. static void FDECL(macCursorMessage, ( EventRecord * , WindowPtr , RgnHandle )) ;
  241. static void FDECL(macCursorTerm, ( EventRecord * , WindowPtr , RgnHandle )) ;
  242. static void FDECL(macCursorMenu, ( EventRecord * , WindowPtr , RgnHandle )) ;
  243. static void FDECL(macCursorText, ( EventRecord * , WindowPtr , RgnHandle )) ;
  244.  
  245. void NDECL(UpdateMenus);
  246. void FDECL(DoMenu, (long choise));
  247.  
  248. static void FDECL (DrawScrollbar, ( NhWindow * , WindowPtr ));
  249. static void FDECL (InvalScrollBar, ( NhWindow * ));
  250. static void FDECL(DoScrollBar,(Point, short, ControlHandle, NhWindow *, WindowPtr));
  251. static pascal void FDECL(Up, (ControlHandle, short));
  252. static pascal void FDECL(Down,(ControlHandle, short));
  253.  
  254. typedef void ( * CbFunc ) ( EventRecord * , WindowPtr ) ;
  255. typedef void ( * CbCursFunc ) ( EventRecord * , WindowPtr , RgnHandle ) ;
  256.  
  257. CbFunc winKeyFuncs [ NUM_FUNCS ] = {
  258.     macKeyNull , macKeyMessage , macKeyTerm , macKeyTerm , macKeyMenu , macKeyText
  259. } ;
  260.  
  261. CbFunc winClickFuncs [ NUM_FUNCS ] = {
  262.     macClickNull , macClickMessage , macClickTerm , macClickTerm , macClickMenu ,
  263.     macClickText
  264. } ;
  265.  
  266. CbFunc winUpdateFuncs [ NUM_FUNCS ] = {
  267.     macUpdateNull , macUpdateMessage , macUpdateTerm , macUpdateTerm ,
  268.     macUpdateMenu , macUpdateText
  269. } ;
  270.  
  271. CbCursFunc winCursorFuncs [ NUM_FUNCS ] = {
  272.     macCursorNull , macCursorMessage , macCursorTerm , macCursorTerm ,
  273.     macCursorMenu , macCursorText
  274. } ;
  275.  
  276. NhWindow *
  277. GetNhWin(WindowPtr mac_win)
  278. {
  279.     int ix;
  280.     for (ix = 0; ix < NUM_MACWINDOWS; ++ix)
  281.         if (mac_win == theWindows[ix].theWindow)
  282.             return theWindows + ix;
  283.     return ((NhWindow *) nil) ;
  284. }
  285.  
  286.  
  287. #ifdef applec
  288.   extern void _DataInit();
  289.   /* This routine is part of the MPW runtime library. This external
  290.      reference to it is done so that we can unload its segment, %A5Init,
  291.      and recover c 250K of memory */
  292. #endif
  293.  
  294.  
  295. void
  296. InitMac( void )
  297. {
  298.     int i ;
  299.     long l ;
  300.     long applLimit;
  301.  
  302. #ifdef applec
  303.     UnloadSeg((Ptr) _DataInit);
  304. #endif
  305.  
  306.     if ( * ( long * ) DefltStack < 50 * 1024L ) {
  307. #ifdef THINK_C
  308.         applLimit = (long) CurStackBase - (50 * 1024L);
  309. #else
  310.         applLimit = (* (long *) CurStackBase) - (50 * 1024L);
  311. #endif
  312.         SetApplLimit ( ( void * ) applLimit ) ;
  313.     }
  314.     MaxApplZone ( ) ;
  315.     for ( i = 0 ; i < 5 ; i ++ )
  316.         MoreMasters ( ) ;
  317.  
  318.     InitGraf ( & qd . thePort ) ;
  319.     InitFonts ( ) ;
  320.     InitWindows ( ) ;
  321.     InitMenus ( ) ;
  322.     InitDialogs ( ( ResumeProcPtr ) 0L ) ;
  323.     TEInit ( ) ;
  324.     InitSegMgmt( itworked );    /* itworked is always in the main segment */
  325.     
  326.     attemptingto("start up");
  327.  
  328.     if ( Gestalt ( gestaltOSAttr , & l ) ) {
  329.         macFlags . processes = 0 ;
  330.         macFlags . tempMem = 0 ;
  331.     } else {
  332.         macFlags . processes = ( l & ( 1 << gestaltLaunchControl ) ) ? 1 : 0 ;
  333.         macFlags . tempMem = ( l & ( 1 << gestaltRealTempMemory ) ) ? 1 : 0 ;
  334.     }
  335.     if ( Gestalt ( gestaltQuickdrawVersion , & l ) ) {
  336.         macFlags . color = 0 ;
  337.     } else {
  338.         macFlags . color = ( l >= gestalt8BitQD ) ? 1 : 0 ;
  339.     }
  340.     if ( Gestalt ( gestaltFindFolderAttr , & l ) ) {
  341.         macFlags . folders = 0 ;
  342.     } else {
  343.         macFlags . folders = ( l & ( 1 << gestaltFindFolderPresent ) ) ? 1 : 0 ;
  344.     }
  345.     if ( Gestalt ( gestaltHelpMgrAttr , & l ) ) {
  346.         macFlags . help = 0 ;
  347.     } else {
  348.         macFlags . help = ( l & ( 1 << gestaltHelpMgrPresent ) ) ? 1 : 0 ;
  349.     }
  350.     if ( Gestalt ( gestaltFSAttr , & l ) ) {
  351.         macFlags . fsSpec = 0 ;
  352.     } else {
  353.         macFlags . fsSpec = ( l & ( 1 << gestaltHasFSSpecCalls ) ) ? 1 : 0 ;
  354.     }
  355.     if ( Gestalt ( gestaltFontMgrAttr , & l ) ) {
  356.         macFlags . trueType = 0 ;
  357.     } else {
  358.         macFlags . trueType = ( l & ( 1 << gestaltOutlineFonts ) ) ? 1 : 0 ;
  359.     }
  360.     if ( Gestalt ( gestaltAUXVersion , & l ) ) {
  361.         macFlags . aux = 0 ;
  362.     } else {
  363.         macFlags . aux = ( l >= 0x200 ) ? 1 : 0 ;
  364.     }
  365.     if ( Gestalt ( gestaltAliasMgrAttr , & l ) ) {
  366.         macFlags . alias = 0 ;
  367.     } else {
  368.         macFlags . alias = ( l & ( 1 << gestaltAliasMgrPresent ) ) ? 1 : 0 ;
  369.     }
  370.     if ( Gestalt ( gestaltStandardFileAttr , & l ) ) {
  371.         macFlags . standardFile = 0 ;
  372.     } else {
  373.         macFlags . standardFile = ( l & ( 1 << gestaltStandardFile58 ) ) ? 1 : 0 ;
  374.     }
  375.  
  376.     gMouseRgn = NewRgn ( ) ;
  377.     InitCursor ( ) ;
  378.     ObscureCursor ( ) ;
  379. }
  380.  
  381.  
  382. #define MAX_HEIGHT 100
  383. #define MIN_HEIGHT 50
  384. #define MIN_WIDTH 300
  385.  
  386. /*
  387.  * This function could be overloaded with any amount of
  388.  * intelligence...
  389.  */
  390. int
  391. SanePositions ( void )
  392. {
  393.     short mainTop , mainLeft ;
  394.     short mesgTop , mesgLeft , mesgWidth , mesgHeight ;
  395.     short left , top , width , height ;
  396.     short ix , numText = 0 , numMenu = 0 ;
  397.     Rect screenArea ;
  398.     WindowPtr theWindow ;
  399.     NhWindow * nhWin ;
  400.  
  401.     screenArea = qd . thePort -> portBits . bounds ;
  402.     OffsetRect ( & screenArea , - screenArea . left , - screenArea . top ) ;
  403.  
  404. /* Map Window */
  405.     nhWin = theWindows + WIN_MAP ;
  406.     theWindow = nhWin -> theWindow ;
  407.  
  408.     height = nhWin -> charHeight * NUM_ROWS ;
  409.     width = nhWin -> charWidth * NUM_COLS ;
  410.  
  411.     if ( ! RetrievePosition ( kMapWindow , & top , & left ) ) {
  412.         top = GetMBarHeight ( ) + ( small_screen ? 2 : 20 ) ;
  413.         left = ( screenArea . right - width ) / 2 ;
  414.     }
  415.  
  416.     mainTop = top ;
  417.     mainLeft = left ;
  418.  
  419. /* Message Window */
  420.     nhWin = theWindows + WIN_MESSAGE ;
  421.     theWindow = nhWin -> theWindow ;
  422.  
  423.     if ( ! RetrievePosition ( kMessageWindow , & top , & left ) ) {
  424.         top = mainTop + _mt_window->portRect.bottom - _mt_window->portRect.top;
  425.         if ( ! small_screen )
  426.             top += 20 ;
  427.         left = mainLeft ;
  428.     }
  429.  
  430.     if ( ! RetrieveSize ( kMessageWindow , top , left , & height , & width ) ) {
  431.         height = screenArea . bottom - top - ( small_screen ? 2-SBARHEIGHT : 2 ) ;
  432.         if ( height > MAX_HEIGHT ) {
  433.             height = MAX_HEIGHT ;
  434.         } else if ( height < MIN_HEIGHT ) {
  435.             height = MIN_HEIGHT ;
  436.             width = MIN_WIDTH ;
  437.             left = screenArea . right - width ;
  438.             top = screenArea . bottom - MIN_HEIGHT ;
  439.         }
  440.     }
  441.     mesgTop = top ;
  442.     mesgLeft = left ;
  443.     mesgHeight = height ;
  444.     mesgWidth = width ;
  445.  
  446. /* Move these windows */
  447.     MoveWindow ( theWindows [ WIN_MESSAGE ] . theWindow , mesgLeft , mesgTop , 1 ) ;
  448.     SizeWindow ( theWindows [ WIN_MESSAGE ] . theWindow , mesgWidth , mesgHeight , 1 ) ;
  449.     MoveWindow ( _mt_window , mainLeft , mainTop , 1 ) ;
  450.  
  451. /* Handle other windows */
  452.     for ( ix = 0 ; ix < NUM_MACWINDOWS ; ix ++ ) {
  453.         if ( ix != WIN_STATUS && ix != WIN_MESSAGE && ix != WIN_MAP && ix != BASE_WINDOW ) {
  454.             if ( theWindow = theWindows [ ix ] . theWindow ) {
  455.                 if ( ( ( WindowPeek ) theWindow ) -> visible ) {
  456.                     if ( theWindows [ ix ] . kind == NHW_MENU ) {
  457.                         if ( ! RetrievePosition ( kMenuWindow , & top , & left ) ) {
  458.                             top = GetMBarHeight ( ) * 2 ;
  459.                             left = 2 ;
  460.                         }
  461.                         top += ( numMenu * GetMBarHeight ( ) ) ;
  462.                         while ( top > screenArea . bottom - MIN_HEIGHT ) {
  463.                             top -= ( screenArea . bottom - GetMBarHeight ( ) * 2 ) ;
  464.                             left += 20 ;
  465.                         }
  466.                         numMenu ++ ;
  467.                         MoveWindow ( theWindow , left , top , 1 ) ;
  468.                     } else {
  469.                         if ( ! RetrievePosition ( kTextWindow , & top , & left ) ) {
  470.                             top = GetMBarHeight ( ) * 2 ;
  471.                             left = screenArea . right - 3 - ( theWindow -> portRect . right -
  472.                                                               theWindow -> portRect . left ) ;
  473.                         }
  474.                         top += ( numText * GetMBarHeight ( ) ) ;
  475.                         while ( top > screenArea . bottom - MIN_HEIGHT ) {
  476.                             top -= ( screenArea . bottom - GetMBarHeight ( ) * 2 ) ;
  477.                             left -= 20 ;
  478.                         }
  479.                         numText ++ ;
  480.                         MoveWindow ( theWindow , left , top , 1 ) ;
  481.                     }
  482.                 }
  483.             }
  484.         }
  485.     }
  486.  
  487.     InitCursor ( ) ;
  488.  
  489.     return 0 ;
  490. }
  491.  
  492.  
  493. winid
  494. mac_create_nhwindow ( int type )
  495. {
  496.     int i ;
  497.     Rect siz ;
  498.     NhWindow * aWin ;
  499.  
  500.     if ( type < NHW_BASE || type > NHW_TEXT ) {
  501.         error ( "Invalid window type %d in create_nhwindow." , type ) ;
  502.         return WIN_ERR ;
  503.     }
  504.  
  505.     for ( i = 0 ; i < NUM_MACWINDOWS ; i ++ ) {
  506.         if ( ! theWindows [ i ] . theWindow )
  507.             break ;
  508.     }
  509.     if ( i >= NUM_MACWINDOWS ) {
  510.         for ( i = 0 ; i < NUM_MACWINDOWS ; i ++ ) {
  511.             WindowPeek w = ( WindowPeek ) theWindows [ i ] . theWindow ;
  512.             if ( w -> visible || i == WIN_INVEN ||
  513.                  w -> windowKind != WIN_BASE_KIND + NHW_MENU &&
  514.                  w -> windowKind != WIN_BASE_KIND + NHW_TEXT )
  515.                 continue ;
  516.             error ( "The window list is getting full, freeing unnecessary window (%d)..." ,
  517.                 i ) ;
  518.             destroy_nhwindow ( i ) ;
  519.             goto got1 ;
  520.         }
  521.         error ( "Out of window ids in create_nhwindow ! (Max = %d)" ,
  522.             NUM_MACWINDOWS ) ;
  523.         return WIN_ERR ;
  524.     }
  525.  
  526. got1 :
  527.     aWin = & theWindows [ i ] ;
  528.  
  529.     aWin -> windowTextLen = 0L ;
  530.     aWin -> clear = 0 ; /* Yes, we need to inval the area on a clear */
  531.     aWin -> scrollBar = (ControlHandle) NULL ;
  532.  
  533.     dprintf ( "Created window type %d" , type ) ;
  534.     aWin -> kind = type ;
  535.     aWin -> keyFunc = winKeyFuncs [ type ] ;
  536.     aWin -> clickFunc = winClickFuncs [ type ] ;
  537.     aWin -> updateFunc = winUpdateFuncs [ type ] ;
  538.     aWin -> cursorFunc = winCursorFuncs [ type ] ;
  539.  
  540.     if (type == NHW_BASE || type == NHW_MAP || type == NHW_STATUS) {
  541.         short x_sz, x_sz_p, y_sz_p;
  542.         dprintf ( "This is in the TTY window" ) ;
  543.         if (type == NHW_BASE) {
  544.             aWin -> keyFunc = winKeyFuncs [ NHW_MAP ] ;
  545.             aWin -> clickFunc = winClickFuncs [ NHW_MAP ] ;
  546.             aWin -> updateFunc = winUpdateFuncs [ NHW_MAP ] ;
  547.             aWin -> cursorFunc = winCursorFuncs [ NHW_MAP ] ;
  548.         } else {
  549.             if (i != tty_create_nhwindow(type)) {
  550.                 dprintf ( "Cannot create window type %d" , type ) ;
  551.             }
  552.             if (type == NHW_MAP) {
  553.                 wins[i]->offy = 0;    /* the message box is in a separate window */
  554.             }
  555.         }
  556.         aWin->theWindow = _mt_window;
  557.         ((WindowPeek)aWin->theWindow)->windowKind = WIN_BASE_KIND + NHW_MAP;
  558.         get_tty_metrics(aWin->theWindow, &x_sz, &aWin->lin, &x_sz_p, &y_sz_p,
  559.                                          &aWin->fontNum, &aWin->fontSize,
  560.                                          &aWin->charWidth, &aWin->charHeight);
  561.         return i;
  562.     }
  563.  
  564.     aWin -> theWindow = GetNewWindow ( WIN_BASE_RES + type ,
  565.         ( WindowPtr ) 0L , ( WindowPtr ) -1L ) ;
  566.     ( ( WindowPeek ) aWin -> theWindow ) -> windowKind = WIN_BASE_KIND
  567.         + type ;
  568.     if ( ! ( aWin -> windowText = NewHandle ( TEXT_BLOCK ) ) ) {
  569.         error ( "NewHandle failed in create_nhwindow (%ld bytes)" ,
  570.             ( long ) TEXT_BLOCK ) ;
  571.         DisposeWindow ( aWin -> theWindow ) ;
  572.         aWin -> theWindow = (WindowPtr) NULL ;
  573.         return WIN_ERR ;
  574.     }
  575.     aWin -> lin = 0 ;
  576.     clear_nhwindow ( i ) ;
  577.  
  578. /*HARDCODED*/
  579.  
  580.     SetPort ( aWin -> theWindow ) ;
  581.     PenPat ( (void *) &qd . black ) ;
  582.  
  583.     switch ( type ) {
  584.         case NHW_MESSAGE :
  585.             GetFNum ( "\pPSHackFont", & aWin -> fontNum ) ;
  586.             aWin -> fontSize = flags.large_font ? 12 : 9 ;
  587.             break ;
  588.         default:
  589.             aWin -> fontNum = text_wind_font ;
  590.             aWin -> fontSize = 9 ;
  591.     }
  592.  
  593.     TextFont ( aWin -> fontNum ) ; 
  594.     TextSize ( aWin -> fontSize ) ;
  595.  
  596.     if (type == NHW_MESSAGE && !top_line) {
  597.         const Rect out_of_scr = { 10000, 10000, 10100, 10100 };
  598.         TextFace(bold);
  599.         top_line = TENew(&out_of_scr, &out_of_scr);
  600.         TEActivate(top_line);
  601.         TextFace(normal);
  602.     }
  603.  
  604.     {
  605.         FontInfo fi ;
  606.         GetFontInfo ( & fi ) ;
  607.         aWin -> leading = fi . leading / 2 + fi . descent ;
  608.         aWin -> charHeight = fi . ascent + fi . descent + fi . leading ;
  609.         aWin -> charWidth = fi . widMax ;
  610.     }
  611.     SetPt ( & ( theWindows [ i ] . cursor ) , 0 , 0 ) ;
  612.  
  613.     siz = aWin -> theWindow -> portRect ;
  614.     OffsetRect ( & siz , 30 + rn2 ( 20 ) , 250 + rn2 ( 50 ) ) ;
  615.     SizeWindow ( aWin -> theWindow , siz . right - siz . left ,
  616.         siz . bottom - siz . top , FALSE ) ;
  617.     MoveWindow ( aWin -> theWindow , siz . left , siz . top , FALSE ) ;
  618.  
  619.     if ( type == NHW_MENU || type == NHW_TEXT || type == NHW_MESSAGE ) {
  620.         Rect r = siz ;
  621.         Boolean bool ;
  622.         OffsetRect ( & r , - r . left , - r . top ) ;
  623.         r . left = r . right - SBARWIDTH ;
  624.         r . bottom -= SBARHEIGHT ;
  625.         r . top -= 1 ;
  626.         r . right += 1 ;
  627.         bool = ( r . bottom > r . top + 50 ) ;
  628.         aWin -> scrollBar = NewControl ( aWin -> theWindow , & r , "\P" ,
  629.             bool , 0 , 0 , 0 , 16 , 0L ) ;
  630.     }
  631.     aWin -> scrollPos = 0 ;
  632.  
  633.     return i ;
  634. }
  635.  
  636.  
  637. static MenuHandle
  638. mustGetMHandle(int menu_id)
  639. {
  640.     MenuHandle menu = GetMHandle(menu_id);
  641.     if (menu == (MenuHandle)  nil) {
  642.         comment("Cannot find the menu.", menu_id);
  643.         ExitToShell();
  644.     }
  645.     return menu;
  646. }
  647.  
  648.  
  649. #define A_LOT 0x7fffffff
  650. #define HEAP_SPACE 100000
  651. #define RES_FACTOR 1.1
  652.  
  653. static long
  654. SpaceToLoad ( char * name ) {
  655. FCBPBRec fcb ;
  656. long ret ;
  657.  
  658.     memset ( & fcb , 0 , sizeof ( fcb ) ) ;
  659.  
  660.     fcb . ioRefNum = CurResFile ( ) ;
  661.     fcb . ioNamePtr = (uchar *) name ;
  662.     if ( PBGetFCBInfoSync ( & fcb ) ) {
  663.         return A_LOT ;
  664.     }
  665.     ret = fcb . ioFCBEOF * RES_FACTOR + HEAP_SPACE ;
  666.     dprintf ( "Space needed %ld" , ret ) ;
  667.     return ret ;
  668. }
  669.  
  670.  
  671. void
  672. InitRes ( void )
  673. {
  674.     InitMenuRes();
  675. }
  676.  
  677.  
  678. void
  679. mac_init_nhwindows ( void )
  680. {
  681.     int i ;
  682.  
  683.     Rect scr = (*GetGrayRgn())->rgnBBox;
  684.     small_screen = scr.bottom - scr.top <=    9*40 ||
  685.                    scr.bottom - scr.top <= 12*40 && flags.large_font;
  686.  
  687.     InitRes ( ) ;
  688.  
  689.     theWindows = ( NhWindow * ) NewPtr ( NUM_MACWINDOWS *
  690.         sizeof ( NhWindow ) ) ;
  691.     mustwork(MemError());
  692.  
  693.     for ( i = 0 ; i < NUM_MACWINDOWS ; i ++ ) {
  694.         theWindows [ i ] . theWindow = (WindowPtr) NULL ;
  695.     }
  696.     for ( i = 0 ; i < QUEUE_LEN ; i ++ ) {
  697.         keyQueue [ i ] = 0 ;
  698.     }
  699.  
  700.     DimMenuBar ( ) ;
  701.  
  702.     tty_init_nhwindows();
  703.     flags.window_inited = TRUE;
  704.  
  705.     /* Some ugly hacks to make both interfaces happy */
  706.     mac_create_nhwindow(NHW_BASE);
  707.     tty_create_nhwindow(NHW_MESSAGE);
  708. }
  709.  
  710.  
  711. void
  712. mac_nhbell ( void )
  713. {
  714.     Handle h ;
  715.  
  716.     if ( h = GetNamedResource ( 'snd ' , "\PNetHack Bell" ) ) {
  717.  
  718.         HLock ( h ) ;
  719.         SndPlay ( ( SndChannelPtr ) NULL , h , 0 ) ;
  720.         ReleaseResource ( h ) ;
  721.  
  722.     } else {
  723.  
  724.         SysBeep ( 30 ) ;
  725.     }
  726. }
  727.  
  728.  
  729. static void
  730. DrawScrollbar ( NhWindow * aWin , WindowPtr theWindow )
  731. {
  732. Rect r2 = theWindow -> portRect ;
  733. Rect r = r2 ;
  734. Boolean vis ;
  735. short val , lin ;
  736.  
  737.     if ( ! aWin -> scrollBar ) {
  738.         return ;
  739.     }
  740.  
  741.     r2 . left = r2 . right - SBARWIDTH ;
  742.     r2 . bottom -= SBARHEIGHT ;
  743.     r2 . right += 1 ;
  744.     r2 . top -= 1 ;
  745.     if ( ( * aWin -> scrollBar ) -> contrlRect . top  != r2 . top ||
  746.          ( * aWin -> scrollBar ) -> contrlRect . left != r2 . left ) {
  747.         MoveControl ( aWin -> scrollBar , r2 . left , r2 . top ) ;
  748.     }
  749.     if ( ( * aWin -> scrollBar ) -> contrlRect . bottom != r2 . bottom ||
  750.          ( * aWin -> scrollBar ) -> contrlRect . right  != r2 . right ) {
  751.         SizeControl ( aWin -> scrollBar , r2 . right  - r2 . left ,
  752.                                           r2 . bottom - r2 . top ) ;
  753.     }
  754.     vis = ( r2 . bottom > r2 . top + 50 ) ;
  755.     if ( vis && ! ( * aWin -> scrollBar ) -> contrlVis ) {
  756.         ShowControl ( aWin -> scrollBar ) ;
  757.     } else if ( ! vis && ( * aWin -> scrollBar ) -> contrlVis ) {
  758.         HideControl ( aWin -> scrollBar ) ;
  759.     }
  760.     lin = aWin -> lin;
  761.     if ( aWin == theWindows + WIN_MESSAGE ) {
  762.         short min ;
  763.         r . bottom -= SBARHEIGHT + 1 ;
  764.         min = aWin -> save_lin + ( r . bottom - r . top ) / aWin ->
  765.             charHeight ;
  766.         if ( lin < min ) {
  767.             lin = min ;
  768.         }
  769.     }
  770.     if ( lin ) {
  771.         short max = lin - ( r . bottom - r . top ) / aWin -> charHeight ;
  772.         if ( max < 0 ) {
  773.             max = 0 ;
  774.         }
  775.         SetCtlMax ( aWin -> scrollBar , max ) ;
  776.         if ( max ) {
  777.             HiliteControl ( aWin -> scrollBar , 0 ) ;
  778.         } else {
  779.             HiliteControl ( aWin -> scrollBar , 255 ) ;
  780.         }
  781.     } else {
  782.         HiliteControl ( aWin -> scrollBar , 255 ) ;
  783.     }
  784.     val = GetCtlValue ( aWin -> scrollBar ) ;
  785.     if ( val != aWin -> scrollPos ) {
  786.         InvalRect ( & ( theWindow -> portRect ) ) ;
  787.         aWin -> scrollPos = val ;
  788.     }
  789.     if ( aWin == asyDSC ) {
  790.         asyDSC = (NhWindow *) NULL ;
  791.     }
  792. }
  793.  
  794.  
  795. static void
  796. InvalScrollBar ( NhWindow * aWin )
  797. {
  798.     if ( asyDSC && asyDSC != aWin ) {
  799.         SetPort ( asyDSC -> theWindow ) ;
  800.         DrawScrollbar ( asyDSC , asyDSC -> theWindow ) ;
  801.     }
  802.     asyDSC = aWin ;
  803. }
  804.  
  805.  
  806. void
  807. mac_clear_nhwindow ( winid win )
  808. {
  809.     long l ;
  810.     Rect r ;
  811.     WindowPtr theWindow ;
  812.     NhWindow * aWin = & theWindows [ win ] ;
  813.  
  814.     if ( win < 0 || win >= NUM_MACWINDOWS ) {
  815.         error ( "Invalid window %d in clear_nhwindow." , win ) ;
  816.         return ;
  817.     }
  818.  
  819.     theWindow = aWin -> theWindow ;
  820.     if (theWindow == _mt_window) {
  821.         tty_clear_nhwindow(win);
  822.         return;
  823.     }
  824.  
  825.     if ( aWin -> clear )
  826.         return ;
  827.     if ( ! theWindow ) {
  828.         error ( "Unallocated window %d in clear_nhwindow." , win ) ;
  829.         return ;
  830.     }
  831.     SetPort ( theWindow ) ;
  832.     r = theWindow -> portRect ;
  833.     if ( aWin -> scrollBar )
  834.         r . right -= SBARWIDTH + 1 ;
  835.     if ( aWin == theWindows + WIN_MESSAGE )
  836.         r . bottom -= SBARHEIGHT + 1 ;
  837.     InvalRect ( & r ) ;
  838.     switch ( ( ( WindowPeek ) theWindow ) -> windowKind - WIN_BASE_KIND ) {
  839.     case NHW_MESSAGE :
  840.         l = 0;
  841.         while (aWin->lin > flags.msg_history) {
  842.             const char cr = CHAR_CR;
  843.             l = Munger(aWin->windowText, l, &cr, 1, nil, 0) + 1;
  844.             --aWin->lin;
  845.         }
  846.         if (l) {
  847.             aWin->windowTextLen -= l;
  848.             BlockMove(*aWin->windowText + l, *aWin->windowText, aWin->windowTextLen);
  849.         }
  850.         aWin->last_more_lin = aWin->lin;
  851.         aWin->save_lin        = aWin->lin;
  852.         aWin->scrollPos = aWin->lin ? aWin->lin - 1 : 0;
  853.         if (aWin->scrollBar) {
  854.             SetCtlMax  (aWin->scrollBar, aWin->lin);
  855.             SetCtlValue(aWin->scrollBar, aWin->scrollPos);
  856.             InvalScrollBar(aWin);
  857.         }
  858.         break ;
  859.     default :
  860.         SetHandleSize ( aWin -> windowText , TEXT_BLOCK ) ;
  861.         aWin -> windowTextLen = 0L ;
  862.         aWin -> lin = 0 ;
  863.         aWin -> wid = 0 ;
  864.         aWin -> scrollPos = 0 ;
  865.         if ( aWin -> scrollBar ) {
  866.             SetCtlMax ( aWin -> scrollBar , 0 ) ;
  867.             InvalScrollBar ( aWin ) ;
  868.         }
  869.         break ;
  870.     }
  871.     SetPt ( & ( aWin -> cursor ) , 0 , 0 ) ;
  872.     aWin -> clear = 1 ;
  873. }
  874.  
  875.  
  876. Boolean
  877. ClosingWindowChar(const int c) {
  878.     return  c == CHAR_ESC || c == CHAR_BLANK || c == CHAR_LF || c == CHAR_CR ||
  879.             c == 'q' ;
  880. }
  881.  
  882.  
  883. #define BTN_IND 2
  884. #define BTN_W    40
  885. #define BTN_H    (SBARHEIGHT-2)
  886.  
  887. static void
  888. topl_resp_rect(int resp_idx, Rect *r)
  889. {
  890.     r->left      = (BTN_IND + BTN_W) * resp_idx + BTN_IND;
  891.     r->right  = r->left + BTN_W;
  892.     r->bottom = theWindows[WIN_MESSAGE].theWindow->portRect.bottom - 1;
  893.     r->top      = r->bottom - BTN_H;
  894. }
  895.  
  896.  
  897. Boolean
  898. in_topl_mode(void)
  899. {
  900.     return top_line &&
  901.            (*top_line)->viewRect.left < theWindows[WIN_MESSAGE].theWindow->portRect.right;
  902. }
  903.  
  904.  
  905. void
  906. enter_topl_mode(char *query)
  907. {
  908.     if (!top_line || in_topl_mode())
  909.         Debugger();
  910.  
  911.     putstr(WIN_MESSAGE, ATR_BOLD, query);
  912.  
  913.     (*top_line)->viewRect.left = 0;
  914.  
  915.     topl_query_len = strlen(query);
  916.     (*top_line)->selStart = topl_query_len;
  917.     (*top_line)->selEnd      = topl_query_len;
  918.     PtrToXHand(query, (*top_line)->hText, topl_query_len);
  919.     TECalText(top_line);
  920.  
  921.     display_nhwindow(WIN_MESSAGE, FALSE);
  922. }
  923.  
  924.  
  925. void
  926. leave_topl_mode(char *answer)
  927. {
  928.     int ans_len = (*top_line)->teLength - topl_query_len;
  929.     NhWindow *aWin = theWindows + WIN_MESSAGE;
  930.  
  931.     if (!in_topl_mode())
  932.         Debugger();
  933.  
  934.     BlockMove(*(*top_line)->hText + topl_query_len, answer, ans_len);
  935.     answer[ans_len] = '\0';
  936.  
  937.     if ( aWin -> windowTextLen > 0 &&
  938.          ( * aWin -> windowText ) [ aWin -> windowTextLen - 1 ] == CHAR_CR ) {
  939.         -- aWin -> windowTextLen ;
  940.         -- aWin -> lin ;
  941.     }
  942.     putstr(WIN_MESSAGE, ATR_BOLD, answer);
  943.  
  944.     (*top_line)->viewRect.left += 10000;
  945. }
  946.  
  947. /*
  948.  * TESetSelect flushes out all the pending key strokes.  I hate it.
  949.  */
  950. static void
  951. topl_set_select(short selStart, short selEnd)
  952. {
  953.     TEDeactivate(top_line);
  954.     (*top_line)->selStart = selStart;
  955.     (*top_line)->selEnd      = selEnd;
  956.     TEActivate(top_line);
  957. }
  958.  
  959.  
  960. static void
  961. topl_replace(char *new_ans)
  962. {
  963.     topl_set_select(topl_query_len, (*top_line)->teLength);
  964.     TEDelete(top_line);
  965.     TEInsert(new_ans, strlen(new_ans), top_line);
  966. }
  967.  
  968.  
  969. Boolean
  970. topl_key(unsigned char ch)
  971. {
  972.     switch (ch) {
  973.         case CHAR_ESC:
  974.             topl_replace("\x1b");
  975.             return false;
  976.         case CHAR_ENTER: case CHAR_CR: case CHAR_LF:
  977.             return false;
  978.  
  979.         case 0x1f & 'P':
  980.             nh_doprev_message();
  981.             return true;
  982.         case '\x1e'/* up arrow */:
  983.             topl_set_select(topl_query_len, topl_query_len);
  984.             return true;
  985.         case CHAR_BS: case '\x1c'/* left arrow */:
  986.             if ((*top_line)->selEnd > topl_query_len)
  987.                 TEKey(ch, top_line);
  988.             return true;
  989.         default:
  990.             TEKey(ch, top_line);
  991.             return true;
  992.     }
  993. }
  994.  
  995.  
  996. Boolean
  997. topl_ext_key(unsigned char ch)
  998. {
  999.     switch (ch) {
  1000.         case CHAR_ESC:
  1001.             topl_replace("\x1b");
  1002.             return false;
  1003.         case CHAR_ENTER: case CHAR_CR: case CHAR_LF:
  1004.             return false;
  1005.  
  1006.         case 0x1f & 'P':
  1007.             nh_doprev_message();
  1008.             return true;
  1009.         case CHAR_BS:
  1010.             topl_replace("");
  1011.             return true;
  1012.         default: {
  1013.             int com_index = -1, oindex = 0;
  1014.             TEInsert(&ch, 1, top_line);
  1015.             while(extcmdlist[oindex].ef_txt != NULL){
  1016.                 if(!strncmpi(*(*top_line)->hText + topl_query_len,
  1017.                              extcmdlist[oindex].ef_txt,
  1018.                              (*top_line)->teLength - topl_query_len))
  1019.                     if(com_index == -1) /* No matches yet*/
  1020.                         com_index = oindex;
  1021.                     else /* More than 1 match */
  1022.                         com_index = -2;
  1023.                 oindex++;
  1024.             }
  1025.             if(com_index >= 0)
  1026.                 topl_replace((char *) extcmdlist[com_index].ef_txt);
  1027.             return true;
  1028.         }
  1029.     }
  1030. }
  1031.  
  1032.  
  1033. void
  1034. topl_flash_resp(int resp_idx)
  1035. {
  1036.     long dont_care;
  1037.     Rect frame;
  1038.     SetPort(theWindows[WIN_MESSAGE].theWindow);
  1039.     topl_resp_rect(resp_idx, &frame);
  1040.     InsetRect(&frame, 1, 1);
  1041.     InvertRect(&frame);
  1042.     Delay(GetDblTime() / 2, &dont_care);
  1043.     InvertRect(&frame);
  1044. }
  1045.  
  1046.  
  1047. void
  1048. topl_set_def(int new_def_idx)
  1049. {
  1050.     Rect frame;
  1051.     SetPort(theWindows[WIN_MESSAGE].theWindow);
  1052.     topl_resp_rect(topl_def_idx, &frame);
  1053.     InvalRect(&frame);
  1054.     topl_def_idx = new_def_idx;
  1055.     topl_resp_rect(new_def_idx, &frame);
  1056.     InvalRect(&frame);
  1057. }
  1058.  
  1059.  
  1060. void
  1061. topl_set_resp(char *resp, char def)
  1062. {
  1063.     char *loc;
  1064.     Rect frame;
  1065.     int r_len, r_len1;
  1066.  
  1067.     if (!resp) {
  1068.         const char any_str[2] = { CHAR_ANY, '\0' };
  1069.         resp = (char *) any_str;
  1070.         def = CHAR_ANY;
  1071.     }
  1072.  
  1073.     SetPort(theWindows[WIN_MESSAGE].theWindow);
  1074.     r_len1 = strlen(resp);
  1075.     r_len  = strlen(topl_resp);
  1076.     if (r_len < r_len1)
  1077.         r_len = r_len1;
  1078.     topl_resp_rect(0, &frame);
  1079.     frame.right = (BTN_IND + BTN_W) * r_len;
  1080.     InvalRect(&frame);
  1081.  
  1082.     strcpy(topl_resp, resp);
  1083.     loc = strchr (resp, def);
  1084.     topl_def_idx = loc ? loc - resp : -1;
  1085. }
  1086.  
  1087.  
  1088. static char
  1089. topl_resp_key(char ch)
  1090. {
  1091.     if (strlen(topl_resp) > 0) {
  1092.         char *loc = strchr(topl_resp, ch);
  1093.  
  1094.         if (!loc)
  1095.             if (ch == '\x9'/* tab */) {
  1096.                 topl_set_def(topl_def_idx <= 0 ? strlen(topl_resp)-1 : topl_def_idx-1);
  1097.                 ch = '\0';
  1098.  
  1099.             } else if (ch == CHAR_ESC) {
  1100.                 loc = strchr(topl_resp, 'q');
  1101.                 if (!loc) {
  1102.                     loc = strchr(topl_resp, 'n');
  1103.                     if (!loc && topl_def_idx >= 0)
  1104.                         loc = topl_resp + topl_def_idx;
  1105.                 }
  1106.  
  1107.             } else if (ch == (0x1f & 'P')) {
  1108.                 nh_doprev_message();
  1109.                 ch = '\0';
  1110.  
  1111.             } else if (topl_def_idx >= 0) {
  1112.                 if ( ch == CHAR_ENTER || ch == CHAR_CR || ch == CHAR_LF ||
  1113.                      ch == CHAR_BLANK || topl_resp[topl_def_idx] == CHAR_ANY )
  1114.                     loc = topl_resp + topl_def_idx;
  1115.  
  1116.                 else if (strchr(topl_resp, '#')) {
  1117.                     if (digit(ch)) {
  1118.                         topl_set_def(strchr(topl_resp, '#') - topl_resp);
  1119.                         TEKey(ch, top_line);
  1120.                         ch = '\0';
  1121.  
  1122.                     } else if (topl_resp[topl_def_idx] == '#')
  1123.                         if (ch == '\x1e'/* up arrow */) {
  1124.                             topl_set_select(topl_query_len, topl_query_len);
  1125.                             ch = '\0';
  1126.                         } else if (ch == '\x1d'/* right arrow */ ||
  1127.                                    ch == '\x1f'/* down arrow */ ||
  1128.                                    (ch == CHAR_BS || ch == '\x1c'/* left arrow */) &&
  1129.                                         (*top_line)->selEnd > topl_query_len) {
  1130.                             TEKey(ch, top_line);
  1131.                             ch = '\0';
  1132.                         }
  1133.                 }
  1134.             }
  1135.  
  1136.         if (loc) {
  1137.             topl_flash_resp(loc - topl_resp);
  1138.             if (*loc != CHAR_ANY)
  1139.                 ch = *loc;
  1140.             TEKey(ch, top_line);
  1141.         }
  1142.     }
  1143.  
  1144.     return ch;
  1145. }
  1146.  
  1147.  
  1148. void
  1149. adjust_window_pos(NhWindow *aWin, WindowPtr theWindow, short w)
  1150. {
  1151. #ifdef THINK_C
  1152.     Rect scr_r   = (*GetGrayRgn())->rgnBBox, win_ind = { 20, 2, 3, 3 };
  1153. #else
  1154.     const Rect scr_r   = (*GetGrayRgn())->rgnBBox, win_ind = { 20, 2, 3, 3 };
  1155. #endif
  1156.     const short    min_w = theWindow->portRect.right - theWindow->portRect.left,
  1157.                 max_w = scr_r.right - scr_r.left - win_ind.left - win_ind.right;
  1158.     Point pos;
  1159.     short h = aWin->lin * aWin->charHeight, max_h;
  1160.  
  1161.     SetPort(theWindow);
  1162.     if (!RetrieveWinPos(theWindow, &pos.v, &pos.h)) {
  1163.         pos.v = theWindow->portRect.top;
  1164.         pos.h = theWindow->portRect.left;
  1165.         LocalToGlobal(&pos);
  1166.     }
  1167.  
  1168.     max_h = full_screen ? scr_r.bottom - win_ind.bottom - scr_r.top - win_ind.top
  1169.                         : scr_r.bottom - win_ind.bottom - pos.v;
  1170.     if (h > max_h      ) h = max_h;
  1171.     if (h < MIN_HEIGHT) h = MIN_HEIGHT;
  1172.     if (w < min_w      ) w = min_w;
  1173.     if (w > max_w      ) w = max_w;
  1174.     SizeWindow(theWindow, w, h, true);
  1175.  
  1176.     if (pos.v + h + win_ind.bottom > scr_r.bottom)
  1177.         pos.v = scr_r.bottom - h - win_ind.bottom;
  1178.     if (pos.h + w + win_ind.right  > scr_r.right)
  1179.         pos.h = scr_r.right     - w - win_ind.right;
  1180.     MoveWindow(theWindow, pos.h, pos.v, false);
  1181. }
  1182.  
  1183.  
  1184. /*
  1185.  * display/select/update the window.
  1186.  * If f is true, this window should be "modal" - don't return
  1187.  * until presumed seen.
  1188.  */
  1189. void
  1190. mac_display_nhwindow ( winid win , BOOLEAN_P f )
  1191. {
  1192.     WindowPtr theWindow ;
  1193.     NhWindow * aWin = & theWindows [ win ] ;
  1194.  
  1195.     if ( win < 0 || win >= NUM_MACWINDOWS ) {
  1196.         error ( "Invalid window %d in display_nhwindow." , win ) ;
  1197.         return ;
  1198.     }
  1199.     theWindow = aWin -> theWindow ;
  1200.     if ( ! theWindow ) {
  1201.         error ( "Unallocated window %d in display_nhwindow." , win ) ;
  1202.         return ;
  1203.     }
  1204.  
  1205.     if (theWindow == _mt_window) {
  1206.         tty_display_nhwindow(win, f);
  1207.         return;
  1208.     }
  1209.  
  1210.     if ( f && inSelect == WIN_ERR && win == WIN_MESSAGE ) {
  1211.         topl_set_resp ( NULL , 0 ) ;
  1212.         if ( aWin -> windowTextLen > 0 &&
  1213.              ( * aWin -> windowText ) [ aWin -> windowTextLen - 1 ] == CHAR_CR ) {
  1214.             -- aWin -> windowTextLen ;
  1215.             -- aWin -> lin ;
  1216.         }
  1217.         putstr ( win , flags . standout ? ATR_INVERSE : ATR_NONE , " --More--" ) ;
  1218.     }
  1219.  
  1220.     if ( ! ( ( WindowPeek ) theWindow ) -> visible || full_screen ) {
  1221.  
  1222.         if ( win != WIN_MESSAGE ) {
  1223.             const char cr = CHAR_CR;
  1224.             short w = 0;
  1225.             long line_start = 0;
  1226.             HLock(aWin->windowText);
  1227.  
  1228.             while (line_start < aWin->windowTextLen) {
  1229.                 long line_end;
  1230.                 short line_w;
  1231.                 line_end = Munger(aWin->windowText, line_start, &cr, 1, nil, 0);
  1232.                 if (line_end < 0)
  1233.                     line_end = aWin->windowTextLen;
  1234.                 line_w = TextWidth(*aWin->windowText, line_start, line_end - line_start);
  1235.                 if (w < line_w)
  1236.                     w = line_w;
  1237.                 line_start = line_end + 1;
  1238.             }
  1239.             HUnlock(aWin->windowText);
  1240.  
  1241.             adjust_window_pos(aWin, theWindow, w + (SBARWIDTH+2));
  1242.         }
  1243.  
  1244.         if ( ! small_screen || win != WIN_MESSAGE || f )
  1245.             SelectWindow ( theWindow ) ;
  1246.         ShowWindow ( theWindow ) ;
  1247.     }
  1248.  
  1249.     SetPort ( theWindow ) ;
  1250.     if ( aWin -> scrollBar ) {
  1251.         InvalScrollBar ( aWin ) ;
  1252.     }
  1253.  
  1254.     if ( f && inSelect == WIN_ERR ) {
  1255.         int ch ;
  1256.  
  1257.         inSelect = win ;
  1258.         do {
  1259.             ch = nhgetch ( ) ;
  1260.         } while ( ! ClosingWindowChar ( ch ) ) ;
  1261.         inSelect = WIN_ERR ;
  1262.  
  1263.         if ( win == WIN_MESSAGE )
  1264.             topl_set_resp ( "" , '\0' ) ;
  1265.         else
  1266.             HideWindow ( theWindow ) ;
  1267.  
  1268.     } else {
  1269.         wait_synch ( ) ;
  1270.     }
  1271. }
  1272.  
  1273.  
  1274. void
  1275. mac_destroy_nhwindow ( winid win )
  1276. {
  1277.     WindowPtr theWindow ;
  1278.     NhWindow * aWin = & theWindows [ win ] ;
  1279.     int kind , visible ;
  1280.  
  1281.     if ( win < 0 || win >= NUM_MACWINDOWS ) {
  1282.         if ( flags . window_inited )
  1283.             error ( "Invalid window number %d (Max %d) in destroy_nhwindow." ,
  1284.                 win , NUM_MACWINDOWS ) ;
  1285.         return ;
  1286.     }
  1287.     theWindow = aWin -> theWindow ;
  1288.     if ( ! theWindow ) {
  1289.         error ( "Not allocated window number %d in destroy_nhwindow." ,
  1290.             win ) ;
  1291.         return ;
  1292.     }
  1293. /*
  1294.  *    if (theWindow == _mt_window) {
  1295.  *        tty_destroy_nhwindow(win);
  1296.  *        return;
  1297.  *    }
  1298.  */
  1299.  
  1300.     /*
  1301.      * Check special windows.
  1302.      * The base window should never go away.
  1303.      * The other "standard" windows should not go away
  1304.      * unless we've exitted nhwindows.
  1305.      */
  1306.     if ( win == BASE_WINDOW ) {
  1307.         return ;
  1308.     }
  1309.     if ( win == WIN_INVEN || win == WIN_MESSAGE ) {
  1310.         if ( flags . window_inited ) {
  1311.             if ( flags . tombstone && killer ) {
  1312.                 /* Prepare for the coming of the tombstone window. */
  1313.                 mono_font ( ) ;
  1314.                 full_screen = TRUE ;
  1315.             }
  1316.             return ;
  1317.         }
  1318.     }
  1319.  
  1320.     kind = ( ( WindowPeek ) theWindow ) -> windowKind - WIN_BASE_KIND ;
  1321.     visible = ( ( WindowPeek ) theWindow ) -> visible ;
  1322.  
  1323.     if ( ( ! visible || ( kind != NHW_MENU && kind != NHW_TEXT ) ) &&
  1324.         theWindow != _mt_window ) {
  1325.         DisposeWindow ( theWindow ) ;
  1326.         if ( aWin -> windowText ) {
  1327.             DisposHandle ( aWin -> windowText ) ;
  1328.         }
  1329.         aWin -> theWindow = (WindowPtr) NULL ;
  1330.         aWin -> windowText = (Handle) NULL ;
  1331.     }
  1332. }
  1333.  
  1334.  
  1335. void
  1336. mac_number_pad ( int pad )
  1337. {
  1338.     macPad = pad ;
  1339. }
  1340.  
  1341.  
  1342. void
  1343. trans_num_keys(EventRecord *theEvent)
  1344. {
  1345.     if (macPad) {
  1346.         Handle h = GetResource('Nump', theEvent->modifiers & shiftKey ? 129 : 128);
  1347.         if (h) {
  1348.             short *ab = (short *)*h;
  1349.             int i = ab[0];
  1350.             while (i) {
  1351.                 if ((theEvent->message & keyCodeMask) == (ab[i] & keyCodeMask)) {
  1352.                     theEvent->message = ab[i];
  1353.                     break;
  1354.                 }
  1355.                 --i;
  1356.             }
  1357.         }
  1358.     }
  1359. }
  1360.  
  1361.  
  1362. /*
  1363.  * Note; theWindow may very well be NULL here, since keyDown may call
  1364.  * it when theres no window !!!
  1365.  */
  1366. void
  1367. GeneralKey ( EventRecord * theEvent , WindowPtr theWindow )
  1368. {
  1369. #if defined(applec)
  1370. # pragma unused(theWindow)
  1371. #endif
  1372.     trans_num_keys ( theEvent ) ;
  1373.     AddToKeyQueue ( topl_resp_key ( theEvent -> message & 0xff ) , 1 ) ;
  1374. }
  1375.  
  1376.  
  1377. static void
  1378. macKeyNull ( EventRecord * theEvent , WindowPtr theWindow )
  1379. {
  1380.     GeneralKey ( theEvent , theWindow ) ;
  1381. }
  1382.  
  1383.  
  1384. static void
  1385. macKeyMessage ( EventRecord * theEvent , WindowPtr theWindow )
  1386. {
  1387.     GeneralKey ( theEvent , theWindow ) ;
  1388. }
  1389.  
  1390.  
  1391. static void
  1392. macKeyTerm ( EventRecord * theEvent , WindowPtr theWindow )
  1393. {
  1394.     GeneralKey ( theEvent , theWindow ) ;
  1395. }
  1396.  
  1397.  
  1398. static void
  1399. macKeyMenu ( EventRecord * theEvent , WindowPtr theWindow )
  1400. {
  1401.     if ( filter_scroll_key ( theEvent -> message & 0xff ,
  1402.         GetNhWin ( theWindow ) ) ) {
  1403.         GeneralKey ( theEvent , theWindow ) ;
  1404.     }
  1405. }
  1406.  
  1407.  
  1408. static void
  1409. macKeyText ( EventRecord * theEvent , WindowPtr theWindow )
  1410. {
  1411.     char c = filter_scroll_key ( theEvent -> message & 0xff ,
  1412.                                  GetNhWin ( theWindow ) ) ;
  1413.     if ( c )
  1414.         if ( inSelect == WIN_ERR && ClosingWindowChar ( c ) ) {
  1415.             HideWindow ( theWindow ) ;
  1416.             destroy_nhwindow ( GetNhWin ( theWindow ) - theWindows ) ;
  1417.         } else {
  1418.             GeneralKey ( theEvent , theWindow ) ;
  1419.         }
  1420. }
  1421.  
  1422.  
  1423. static void
  1424. macClickNull ( EventRecord * theEvent , WindowPtr theWindow )
  1425. {
  1426.     if ( ! theEvent || ! theWindow ) {
  1427.         Debugger ( ) ;
  1428.     }
  1429. }
  1430.  
  1431.  
  1432. static void
  1433. macClickMessage ( EventRecord * theEvent , WindowPtr theWindow )
  1434. {
  1435.     int r_idx = 0;
  1436.     Point mouse = theEvent->where;
  1437.     GlobalToLocal(&mouse);
  1438.     while (topl_resp[r_idx]) {
  1439.         Rect frame;
  1440.         topl_resp_rect(r_idx, &frame);
  1441.         InsetRect(&frame, 1, 1);
  1442.         if (PtInRect(mouse, &frame)) {
  1443.  
  1444.             Boolean in_btn = true;
  1445.             InvertRect(&frame);
  1446.             while (WaitMouseUp()) {
  1447.                 SystemTask();
  1448.                 GetMouse(&mouse);
  1449.                 if (PtInRect(mouse, &frame) != in_btn) {
  1450.                     in_btn = !in_btn;
  1451.                     InvertRect(&frame);
  1452.                 }
  1453.             }
  1454.             if (in_btn) {
  1455.                 InvertRect(&frame);
  1456.                 AddToKeyQueue ( topl_resp [ r_idx ] , 1 ) ;
  1457.             }
  1458.             return;
  1459.  
  1460.         }
  1461.         ++r_idx;
  1462.     }
  1463.  
  1464.     macClickText(theEvent, theWindow);
  1465. }
  1466.  
  1467.  
  1468. static void
  1469. macClickTerm ( EventRecord * theEvent , WindowPtr theWindow )
  1470. {
  1471.     int shift_down = theEvent->modifiers & shiftKey;
  1472.     NhWindow *nhw = GetNhWin(theWindow);
  1473.     Point where = theEvent->where;
  1474.         GlobalToLocal(&where);
  1475.         where.h = where.h / nhw->charWidth + 1;
  1476.         where.v = where.v / nhw->charHeight;
  1477.     clicked_mod = shift_down ? CLICK_2 : CLICK_1;
  1478.  
  1479.     if (strchr(topl_resp, click_to_cmd(where.h, where.v, clicked_mod)))
  1480.         nhbell();
  1481.     else {
  1482.         if (cursor_locked)
  1483.             while (WaitMouseUp())
  1484.                 SystemTask();
  1485.         else if (!shift_down)
  1486.             gNextClickRepeat = TickCount() + *(short *)KeyThresh;
  1487.         gClickedToMove = TRUE;
  1488.         clicked_pos = where;
  1489.     }
  1490. }
  1491.  
  1492. static amtToScroll = 0 ;
  1493. static NhWindow * winToScroll = (NhWindow *) NULL ;
  1494.  
  1495. static pascal void
  1496. Up ( ControlHandle theBar , short part )
  1497. {
  1498.     EventRecord fake ;
  1499.     short now = GetCtlValue ( theBar ) ;
  1500.     short min = GetCtlMin ( theBar ) ;
  1501.     Rect r ;
  1502.     RgnHandle rgn = NewRgn ( ) ;
  1503.  
  1504.     if ( ! part ) {
  1505.         return ;
  1506.     }
  1507.  
  1508.     if ( now - min < amtToScroll ) {
  1509.         amtToScroll = now - min ;
  1510.     }
  1511.     if ( ! amtToScroll ) {
  1512.         return ;
  1513.     }
  1514.     SetCtlValue ( theBar , now - amtToScroll ) ;
  1515.     winToScroll -> scrollPos = now - amtToScroll ;
  1516.     r = winToScroll -> theWindow -> portRect ;
  1517.     r . right -= SBARWIDTH ;
  1518.     if ( winToScroll == theWindows + WIN_MESSAGE )
  1519.         r . bottom -= SBARHEIGHT + 1 ;
  1520.     ScrollRect ( & r , 0 , amtToScroll * winToScroll -> charHeight , rgn ) ;
  1521.     if ( rgn ) {
  1522.         InvalRgn ( rgn ) ;
  1523.         BeginUpdate ( winToScroll -> theWindow ) ;
  1524.     }
  1525.     winToScroll -> updateFunc  ( & fake , winToScroll -> theWindow ) ;
  1526.     if ( rgn ) {
  1527.         EndUpdate ( winToScroll -> theWindow ) ;
  1528.         DisposeRgn ( rgn ) ;
  1529.     }
  1530. }
  1531.  
  1532.  
  1533. static pascal void
  1534. Down ( ControlHandle theBar , short part )
  1535. {
  1536.     EventRecord fake ;
  1537.     short now = GetCtlValue ( theBar ) ;
  1538.     short max = GetCtlMax ( theBar ) ;
  1539.     Rect r ;
  1540.     RgnHandle rgn = NewRgn ( ) ;
  1541.  
  1542.     if ( ! part ) {
  1543.         return ;
  1544.     }
  1545.  
  1546.     if ( max - now < amtToScroll ) {
  1547.         amtToScroll = max - now ;
  1548.     }
  1549.     if ( ! amtToScroll ) {
  1550.         return ;
  1551.     }
  1552.     SetCtlValue ( theBar , now + amtToScroll ) ;
  1553.     winToScroll -> scrollPos = now + amtToScroll ;
  1554.     r = winToScroll -> theWindow -> portRect ;
  1555.     r . right -= SBARWIDTH ;
  1556.     if ( winToScroll == theWindows + WIN_MESSAGE )
  1557.         r . bottom -= SBARHEIGHT + 1 ;
  1558.     ScrollRect ( & r , 0 , - amtToScroll * winToScroll -> charHeight , rgn ) ; 
  1559.     if ( rgn ) {
  1560.         InvalRgn ( rgn ) ;
  1561.         BeginUpdate ( winToScroll -> theWindow ) ;
  1562.     }
  1563.     winToScroll -> updateFunc  ( & fake , winToScroll -> theWindow ) ;
  1564.     if ( rgn ) {
  1565.         EndUpdate ( winToScroll -> theWindow ) ;
  1566.         DisposeRgn ( rgn ) ;
  1567.     }
  1568. }
  1569.  
  1570.  
  1571. static void
  1572. DoScrollBar ( Point p , short code , ControlHandle theBar , NhWindow * aWin ,
  1573.     WindowPtr theWindow )
  1574. {
  1575.     pascal void ( * func ) ( ControlHandle , short ) = 0 ;
  1576.  
  1577.     winToScroll = aWin ;
  1578.     switch ( code ) {
  1579.     case inUpButton :
  1580.         func = Up ;
  1581.         amtToScroll = 1 ;
  1582.         break ;
  1583.     case inDownButton :
  1584.         func = Down ;
  1585.         amtToScroll = 1 ;
  1586.         break ;
  1587.     case inPageUp :
  1588.         func = Up ;
  1589.         amtToScroll = ( theWindow -> portRect . bottom - theWindow ->
  1590.             portRect . top ) / aWin -> charHeight ;
  1591.         break ;
  1592.     case inPageDown :
  1593.         func = Down ;
  1594.         amtToScroll = ( theWindow -> portRect . bottom - theWindow ->
  1595.             portRect . top ) / aWin -> charHeight ;
  1596.         break ;
  1597.     default :
  1598.         break ;
  1599.     }
  1600.  
  1601.     ( void ) TrackControl ( theBar , p , ( ProcPtr ) func );
  1602.     if ( ! func ) {
  1603.         if ( aWin -> scrollPos != GetCtlValue ( theBar ) ) {
  1604.             aWin -> scrollPos = GetCtlValue ( theBar ) ;
  1605.             InvalRect ( & ( theWindow -> portRect ) ) ;
  1606.         }
  1607.     }
  1608. }
  1609.  
  1610.  
  1611. int
  1612. filter_scroll_key(const int ch, NhWindow *aWin)
  1613. {
  1614.     if (aWin->scrollBar && GetCtlValue(aWin->scrollBar) < GetCtlMax(aWin->scrollBar)) {
  1615.         winToScroll = aWin;
  1616.         SetPort(aWin->theWindow);
  1617.         if (ch == CHAR_BLANK) {
  1618.             amtToScroll = ( aWin->theWindow->portRect.bottom
  1619.                           - aWin->theWindow->portRect.top ) / aWin->charHeight;
  1620.             Down(aWin->scrollBar, inPageDown);
  1621.             return 0;
  1622.         }
  1623.         if (ch == CHAR_CR || ch == CHAR_LF) {
  1624.             amtToScroll = 1;
  1625.             Down(aWin->scrollBar, inDownButton);
  1626.             return 0;
  1627.         }
  1628.     }
  1629.     return ch;
  1630. }
  1631.  
  1632.  
  1633. int
  1634. mac_doprev_message(void)
  1635. {
  1636.     if (WIN_MESSAGE) {
  1637.         display_nhwindow(WIN_MESSAGE, FALSE);
  1638.         amtToScroll = 1;
  1639.         winToScroll = &theWindows[WIN_MESSAGE];
  1640.         SetPort(winToScroll->theWindow);
  1641.         Up(winToScroll->scrollBar, inUpButton);
  1642.     }    
  1643.     return 0 ;
  1644. }
  1645.  
  1646.  
  1647. static void
  1648. macClickMenu ( EventRecord * theEvent , WindowPtr theWindow )
  1649. {
  1650.     Point p ;
  1651.     short hiRow = -1 , loRow = -1 ;
  1652.     Rect r ;
  1653.     NhWindow * aWin = GetNhWin ( theWindow ) ;
  1654.  
  1655.     r = theWindow -> portRect ;
  1656.     if ( aWin -> scrollBar && ( * aWin -> scrollBar ) -> contrlVis ) {
  1657.         short code ;
  1658.         Point p = theEvent -> where ;
  1659.         ControlHandle theBar ;
  1660.  
  1661.         r . right -= SBARWIDTH ;
  1662.         GlobalToLocal ( & p ) ;
  1663.         code = FindControl ( p , theWindow , & theBar ) ;
  1664.         if ( code ) {
  1665.             DoScrollBar ( p , code , theBar , aWin , theWindow ) ;
  1666.             return ;
  1667.         }
  1668.         if ( p . h >= r . right )
  1669.             return ;
  1670.     }
  1671.     r . top = r . bottom = 0 ;
  1672.     if ( inSelect != WIN_ERR ) {
  1673.         do {
  1674.             SystemTask ( ) ;
  1675.             GetMouse ( & p ) ;
  1676.             if ( p . h < theWindow -> portRect . left || p . h > theWindow ->
  1677.                 portRect . right || p . v < 0 || p . v > theWindow -> portRect .
  1678.                 bottom ) {
  1679.                 hiRow = -1 ;
  1680.             } else {
  1681.                 hiRow = p . v / aWin -> charHeight ;
  1682.                 if ( hiRow >= aWin -> lin )
  1683.                     hiRow = -1 ;
  1684.             }
  1685.             if ( hiRow != loRow ) {
  1686.                 if ( loRow > -1 && aWin -> itemChars [ loRow + aWin ->
  1687.                     scrollPos ] ) {
  1688.                     r . top = loRow * aWin -> charHeight ;
  1689.                     r . bottom = ( loRow + 1 ) * aWin -> charHeight ;
  1690.                     InvertRect ( & r ) ;
  1691.                 }
  1692.                 loRow = hiRow ;
  1693.                 if ( loRow > -1 && aWin -> itemChars [ loRow + aWin ->
  1694.                     scrollPos ] ) {
  1695.                     r . top = loRow * aWin -> charHeight ;
  1696.                     r . bottom = ( loRow + 1 ) * aWin -> charHeight ;
  1697.                     InvertRect ( & r ) ;
  1698.                 }
  1699.             }
  1700.         } while ( StillDown ( ) ) ;
  1701.         if ( loRow > -1 && aWin -> itemChars [ loRow + aWin -> scrollPos ] ) {
  1702.             InvertRect ( & r ) ;
  1703.             AddToKeyQueue ( aWin -> itemChars [ loRow + aWin -> scrollPos ] , 1 ) ;
  1704.         }
  1705.     }
  1706. }
  1707.  
  1708.  
  1709. static void
  1710. macClickText ( EventRecord * theEvent , WindowPtr theWindow )
  1711. {
  1712.     short hiRow = -1 , loRow = -1 ;
  1713.     Rect r ;
  1714.     NhWindow * aWin = GetNhWin ( theWindow ) ;
  1715.  
  1716.     r = theWindow -> portRect ;
  1717.     if ( aWin -> scrollBar && ( * aWin -> scrollBar ) -> contrlVis ) {
  1718.         short code ;
  1719.         Point p = theEvent -> where ;
  1720.         ControlHandle theBar ;
  1721.  
  1722.         r . right -= SBARWIDTH ;
  1723.         GlobalToLocal ( & p ) ;
  1724.         code = FindControl ( p , theWindow , & theBar ) ;
  1725.         if ( code ) {
  1726.             DoScrollBar ( p , code , theBar , aWin , theWindow ) ;
  1727.             return ;
  1728.         }
  1729.     }
  1730. }
  1731.  
  1732.  
  1733. static void
  1734. macUpdateNull ( EventRecord * theEvent , WindowPtr theWindow )
  1735. {
  1736.     if ( ! theEvent || ! theWindow ) {
  1737.         Debugger ( ) ;
  1738.     }
  1739. }
  1740.  
  1741.  
  1742. static void
  1743. draw_growicon_vert_only(WindowPtr wind) {
  1744.     GrafPtr org_port;
  1745.     RgnHandle org_clip = NewRgn();
  1746.     Rect r = wind->portRect;
  1747.     r.left = r.right - SBARWIDTH;
  1748.  
  1749.     GetPort(&org_port);
  1750.     SetPort(wind);
  1751.     GetClip(org_clip);
  1752.     ClipRect(&r);
  1753.     DrawGrowIcon(wind);
  1754.     SetClip(org_clip);
  1755.     DisposeRgn(org_clip);
  1756.     SetPort(org_port);
  1757. }
  1758.  
  1759.  
  1760. static void
  1761. macUpdateMessage ( EventRecord * theEvent , WindowPtr theWindow )
  1762. {
  1763.     RgnHandle org_clip = NewRgn(), clip = NewRgn();
  1764.     Rect r = theWindow -> portRect ;
  1765.     NhWindow * aWin = GetNhWin ( theWindow ) ;
  1766.     int l ;
  1767.  
  1768.     if ( ! theEvent ) {
  1769.         Debugger ( ) ;
  1770.     }
  1771.  
  1772.     GetClip(org_clip);
  1773.  
  1774.     DrawControls(theWindow);
  1775.     DrawGrowIcon(theWindow);
  1776.  
  1777.     l = 0;
  1778.     while (topl_resp[l]) {
  1779.         StringPtr name;
  1780.         unsigned char tmp[2];
  1781.         FontInfo font;
  1782.         Rect frame;
  1783.         topl_resp_rect(l, &frame);
  1784.         switch (topl_resp[l]) {
  1785.             case 'y':
  1786.                 name = "\pyes";
  1787.                 break;
  1788.             case 'n':
  1789.                 name = "\pno";
  1790.                 break;
  1791.             case 'N':
  1792.                 name = "\pNone";
  1793.                 break;
  1794.             case 'a':
  1795.                 name = "\pall";
  1796.                 break;
  1797.             case 'q':
  1798.                 name = "\pquit";
  1799.                 break;
  1800.             case CHAR_ANY:
  1801.                 name = "\pany key";
  1802.                 break;
  1803.             default:
  1804.                 tmp[0] = 1;
  1805.                 tmp[1] = topl_resp[l];
  1806.                 name = tmp;
  1807.                 break;
  1808.         }
  1809.         TextFont(geneva);
  1810.         TextSize(9);
  1811.         GetFontInfo(&font);
  1812.         MoveTo((frame.left + frame.right  - StringWidth(name)) / 2,
  1813.                (frame.top  + frame.bottom + font.ascent-font.descent-font.leading-1) / 2);
  1814.         DrawString(name);
  1815.         PenNormal();
  1816.         if (l == topl_def_idx)
  1817.             PenSize(2, 2);
  1818.         FrameRoundRect(&frame, 4, 4);
  1819.         ++l;
  1820.     }
  1821.  
  1822.     r . right -= SBARWIDTH + 2;
  1823.     r . bottom -= SBARHEIGHT + 1;
  1824.     /* Clip to the portrect - scrollbar/growicon *before* adjusting the rect
  1825.         to be larger than the size of the window (!) */
  1826.     RectRgn(clip, &r);
  1827.     SectRgn(clip, org_clip, clip);
  1828.     if ( r . right < MIN_RIGHT )
  1829.         r . right = MIN_RIGHT ;
  1830.     r . top -= aWin -> scrollPos * aWin -> charHeight ;
  1831.  
  1832. #if 0
  1833.     /* If you enable this band of code (and disable the next band), you will get
  1834.        fewer flickers but a slower performance while drawing the dot line. */
  1835.     {    RgnHandle dotl_rgn = NewRgn();
  1836.         Rect dotl;
  1837.         dotl.left    = r.left;
  1838.         dotl.right    = r.right;
  1839.         dotl.bottom = r.top + aWin->save_lin * aWin->charHeight;
  1840.         dotl.top    = dotl.bottom - 1;
  1841.         FillRect(&dotl, &qd.gray);
  1842.         RectRgn(dotl_rgn, &dotl);
  1843.         DiffRgn(clip, dotl_rgn, clip);
  1844.         DisposeRgn(dotl_rgn);
  1845.         SetClip(clip);
  1846.     }
  1847. #endif
  1848.  
  1849.     if (in_topl_mode()) {
  1850.         RgnHandle topl_rgn = NewRgn();
  1851.         Rect topl_r = r;
  1852.         topl_r.top += (aWin->lin - 1) * aWin->charHeight;
  1853.         l = (*top_line)->destRect.right - (*top_line)->destRect.left;
  1854.         (*top_line)->viewRect = topl_r;
  1855.         (*top_line)->destRect = topl_r;
  1856.         if (l != topl_r.right - topl_r.left)
  1857.             TECalText(top_line);
  1858.         TEUpdate(&topl_r, top_line);
  1859.         RectRgn(topl_rgn, &topl_r);
  1860.         DiffRgn(clip, topl_rgn, clip);
  1861.         DisposeRgn(topl_rgn);
  1862.         SetClip(clip);
  1863.     }
  1864.  
  1865.     DisposeRgn(clip);
  1866.  
  1867.     TextFont ( aWin -> fontNum ) ;
  1868.     TextSize ( aWin -> fontSize ) ;
  1869.     HLock ( aWin -> windowText ) ;
  1870.     TextBox ( * aWin -> windowText , aWin -> windowTextLen , & r , teJustLeft ) ;
  1871.     HUnlock ( aWin -> windowText ) ;
  1872.  
  1873. #if 1
  1874.     r.bottom = r.top + aWin->save_lin * aWin->charHeight;
  1875.     r.top     = r.bottom - 1;
  1876.     FillRect(&r, (void *) &qd.gray);
  1877. #endif
  1878.  
  1879.     SetClip(org_clip);
  1880.     DisposeRgn(org_clip);
  1881. }
  1882.  
  1883.  
  1884. static void
  1885. macUpdateTerm ( EventRecord * theEvent , WindowPtr theWindow )
  1886. {
  1887. #if defined(applec)
  1888. # pragma unused(theEvent)
  1889. #endif
  1890.     tty_environment_changed ( theWindow ) ;
  1891.     image_tty(theWindow);
  1892. }
  1893.  
  1894.  
  1895. static void
  1896. macUpdateMenu ( EventRecord * theEvent , WindowPtr theWindow )
  1897. {
  1898.     Rect r = theWindow -> portRect ;
  1899.     Rect r2 = r ;
  1900.     NhWindow * aWin = GetNhWin ( theWindow ) ;
  1901.     RgnHandle h ;
  1902.     Boolean vis ;
  1903.  
  1904.     if ( ! theEvent ) {
  1905.         Debugger ( ) ;
  1906.     }
  1907.  
  1908.     draw_growicon_vert_only(theWindow);
  1909.  
  1910.     r2 . left = r2 . right - SBARWIDTH ;
  1911.     r2 . right += 1 ;
  1912.     r2 . top -= 1 ;
  1913.     vis = ( r2 . bottom > r2 . top + 50 ) ;
  1914.     DrawControls ( theWindow ) ;
  1915.  
  1916.     h = (RgnHandle) NULL ;
  1917.     if ( vis && ( h = NewRgn ( ) ) ) {
  1918.         RgnHandle tmp = NewRgn ( ) ;
  1919.         if ( ! tmp ) {
  1920.             DisposeRgn ( h ) ;
  1921.             h = (RgnHandle) NULL ;
  1922.         } else {
  1923.             GetClip ( h ) ;
  1924.             RectRgn ( tmp , & r2 ) ;
  1925.             DiffRgn ( h , tmp , tmp ) ;
  1926.             SetClip ( tmp ) ;
  1927.             DisposeRgn ( tmp ) ;
  1928.         }
  1929.     }
  1930.     if ( r . right < MIN_RIGHT )
  1931.         r . right = MIN_RIGHT ;
  1932.     r . top -= aWin -> scrollPos * aWin -> charHeight ;
  1933.     HLock ( aWin -> windowText ) ;
  1934.     TextBox ( * aWin -> windowText , aWin -> windowTextLen , & r , teJustLeft ) ;
  1935.     HUnlock ( aWin -> windowText ) ;
  1936.     if ( h ) {
  1937.         SetClip ( h ) ;
  1938.         DisposeRgn ( h ) ;
  1939.     }
  1940. }
  1941.  
  1942.  
  1943. static void
  1944. macUpdateText ( EventRecord * theEvent , WindowPtr theWindow )
  1945. {
  1946.     Rect r = theWindow -> portRect ;
  1947.     Rect r2 = r ;
  1948.     NhWindow * aWin = GetNhWin ( theWindow ) ;
  1949.     RgnHandle h ;
  1950.     Boolean vis ;
  1951.  
  1952.     if ( ! theEvent ) {
  1953.         Debugger ( ) ;
  1954.     }
  1955.  
  1956.     r2 . left = r2 . right - SBARWIDTH ;
  1957.     r2 . right += 1 ;
  1958.     r2 . top -= 1 ;
  1959.     vis = ( r2 . bottom > r2 . top + 50 ) ;
  1960.     DrawControls ( theWindow ) ;
  1961.  
  1962.     h = (RgnHandle) NULL ;
  1963.     if ( vis && ( h = NewRgn ( ) ) ) {
  1964.         RgnHandle tmp = NewRgn ( ) ;
  1965.         if ( ! tmp ) {
  1966.             DisposeRgn ( h ) ;
  1967.             h = (RgnHandle) NULL ;
  1968.         } else {
  1969.             GetClip ( h ) ;
  1970.             RectRgn ( tmp , & r2 ) ;
  1971.             DiffRgn ( h , tmp , tmp ) ;
  1972.             SetClip ( tmp ) ;
  1973.             DisposeRgn ( tmp ) ;
  1974.         }
  1975.     }
  1976.     if ( r . right < MIN_RIGHT )
  1977.         r . right = MIN_RIGHT ;
  1978.     r . top -= aWin -> scrollPos * aWin -> charHeight ;
  1979.     r . right -= SBARWIDTH;
  1980.     HLock ( aWin -> windowText ) ;
  1981.     TextBox ( * aWin -> windowText , aWin -> windowTextLen , & r , teJustLeft ) ;
  1982.     HUnlock ( aWin -> windowText ) ;
  1983.     draw_growicon_vert_only(theWindow);
  1984.     if ( h ) {
  1985.         SetClip ( h ) ;
  1986.         DisposeRgn ( h ) ;
  1987.     }
  1988. }
  1989.  
  1990.  
  1991. static void
  1992. macCursorNull ( EventRecord * theEvent , WindowPtr theWindow , RgnHandle mouseRgn )
  1993. {
  1994. #if defined(applec)
  1995. # pragma unused(theWindow)
  1996. #endif
  1997.     Rect r = { -1 , -1 , 2 , 2 } ;
  1998.  
  1999.     InitCursor ( ) ;
  2000.     OffsetRect ( & r , theEvent -> where . h , theEvent -> where . v ) ;
  2001.     RectRgn ( mouseRgn , & r ) ;
  2002. }
  2003.  
  2004.  
  2005. static void
  2006. macCursorMessage ( EventRecord * theEvent , WindowPtr theWindow , RgnHandle mouseRgn )
  2007. {
  2008. #if defined(applec)
  2009. # pragma unused(theWindow)
  2010. #endif
  2011.     Rect r = { -1 , -1 , 2 , 2 } ;
  2012.  
  2013.     InitCursor ( ) ;
  2014.     OffsetRect ( & r , theEvent -> where . h , theEvent -> where . v ) ;
  2015.     RectRgn ( mouseRgn , & r ) ;
  2016. }
  2017.  
  2018.  
  2019. static void
  2020. macCursorTerm ( EventRecord * theEvent , WindowPtr theWindow , RgnHandle mouseRgn )
  2021. {
  2022.     Point where ;
  2023.     char * dir_bas , * dir ;
  2024.     CursHandle ch ;
  2025.     GrafPtr gp ;
  2026.     NhWindow * nhw = GetNhWin ( theWindow ) ;
  2027.     Rect r = { 0 , 0 , 1 , 1 } ;
  2028.  
  2029.     GetPort ( & gp ) ;
  2030.     SetPort ( theWindow ) ;
  2031.  
  2032.     where = theEvent -> where ;
  2033.     GlobalToLocal ( & where ) ;
  2034.  
  2035.     if ( cursor_locked )
  2036.         dir = NULL ;
  2037.     else {
  2038.         dir_bas = flags . num_pad ? (char *) ndir : (char *) sdir ;
  2039.         dir = strchr ( dir_bas , click_to_cmd ( where . h / nhw -> charWidth + 1 ,
  2040.                                                 where . v / nhw -> charHeight ,
  2041.                                                 CLICK_1 ) ) ;
  2042.     }
  2043.     ch = GetCursor ( dir ? dir - dir_bas + 513 : 512 ) ;
  2044.     if ( ch ) {
  2045.  
  2046.         HLock ( ( Handle ) ch ) ;
  2047.         SetCursor ( * ch ) ;
  2048.         HUnlock ( ( Handle ) ch ) ;
  2049.  
  2050.     } else {
  2051.  
  2052.         InitCursor ( ) ;
  2053.     }
  2054.     OffsetRect ( & r , theEvent -> where . h , theEvent -> where . v ) ;
  2055.     RectRgn ( mouseRgn , & r ) ;
  2056.  
  2057.     SetPort ( gp ) ;
  2058. }
  2059.  
  2060.  
  2061. static void
  2062. macCursorMenu ( EventRecord * theEvent , WindowPtr theWindow , RgnHandle mouseRgn )
  2063. {
  2064. #if defined(applec)
  2065. # pragma unused(theWindow)
  2066. #endif
  2067.     Rect r = { -1 , -1 , 2 , 2 } ;
  2068.  
  2069.     InitCursor ( ) ;
  2070.     OffsetRect ( & r , theEvent -> where . h , theEvent -> where . v ) ;
  2071.     RectRgn ( mouseRgn , & r ) ;
  2072. }
  2073.  
  2074.  
  2075. static void
  2076. macCursorText ( EventRecord * theEvent , WindowPtr theWindow , RgnHandle mouseRgn )
  2077. {
  2078. #if defined(applec)
  2079. # pragma unused(theWindow)
  2080. #endif
  2081.     Rect r = { -1 , -1 , 2 , 2 } ;
  2082.  
  2083.     InitCursor ( ) ;
  2084.     OffsetRect ( & r , theEvent -> where . h , theEvent -> where . v ) ;
  2085.     RectRgn ( mouseRgn , & r ) ;
  2086. }
  2087.  
  2088.  
  2089. void
  2090. UpdateMenus ( void )
  2091. {
  2092.     extern void AdjustMenus(short);
  2093.  
  2094.     AdjustMenus(0);
  2095. }
  2096.  
  2097.  
  2098. void
  2099. DoMenu ( long choise )
  2100. {
  2101.     extern void DoMenuEvt(long);
  2102.  
  2103.     DoMenuEvt(choise);
  2104. }
  2105.  
  2106.  
  2107. void
  2108. HandleKey ( EventRecord * theEvent )
  2109. {
  2110.     WindowPtr theWindow = FrontWindow ( ) ;
  2111.  
  2112.     if ( theEvent -> modifiers & cmdKey ) {
  2113.         if ( theEvent -> message & 0xff == '.' ) {
  2114.             int i ;
  2115. /* Flush key queue */
  2116.             for ( i = 0 ; i < QUEUE_LEN ; i ++ ) {
  2117.                 keyQueue [ i ] = 0 ;
  2118.             }
  2119.             theEvent -> message = '\033' ;
  2120.             goto dispatchKey ;
  2121.         } else {
  2122.             UpdateMenus ( ) ;
  2123.             DoMenu ( MenuKey ( theEvent -> message & 0xff ) ) ;
  2124.         }
  2125.     } else {
  2126.  
  2127. dispatchKey :
  2128.         if ( theWindow ) {
  2129.             GetNhWin ( theWindow ) -> keyFunc ( theEvent , theWindow ) ;
  2130.         } else {
  2131.             GeneralKey ( theEvent , (WindowPtr) NULL ) ;
  2132.         }
  2133.     }
  2134. }
  2135.  
  2136.  
  2137. void
  2138. HandleClick ( EventRecord * theEvent )
  2139. {
  2140.     int code ;
  2141.     unsigned long l ;
  2142.     WindowPtr theWindow ;
  2143.     Rect r = ( * GetGrayRgn ( ) ) -> rgnBBox ;
  2144.     NhWindow * aWin ;
  2145.  
  2146.     InsetRect ( & r , 4 , 4 ) ;
  2147.  
  2148.     code = FindWindow ( theEvent -> where , & theWindow ) ;
  2149.     aWin = GetNhWin ( theWindow ) ;
  2150.  
  2151.     if ( code != inContent ) {
  2152.         InitCursor ( ) ;
  2153.     } else {
  2154.         aWin -> cursorFunc ( theEvent , theWindow , gMouseRgn ) ; /* Correct direction */
  2155.     }
  2156.     switch ( code ) {
  2157.  
  2158.     case inContent :
  2159.         if ( inSelect == WIN_ERR || aWin - theWindows == inSelect ) {
  2160.             SelectWindow ( theWindow ) ;
  2161.             SetPort ( theWindow ) ;
  2162.             GetNhWin ( theWindow ) -> clickFunc ( theEvent , theWindow ) ;
  2163.         } else {
  2164.             nhbell ( ) ;
  2165.         }
  2166.         break ;
  2167.  
  2168.     case inDrag :
  2169.         if ( inSelect == WIN_ERR || aWin - theWindows == inSelect ) {
  2170.             InitCursor ( ) ;
  2171.             DragWindow ( theWindow , theEvent -> where , & r ) ;
  2172.             SaveWindowPos ( theWindow ) ;
  2173.         } else {
  2174.             nhbell ( ) ;
  2175.         }
  2176.         break ;
  2177.  
  2178.     case inGrow :
  2179.         if ( inSelect == WIN_ERR || aWin - theWindows == inSelect ) {
  2180.             InitCursor ( ) ;
  2181.             SetRect ( & r , 80 , 2 * aWin -> charHeight + 1 , r . right ,
  2182.                 r . bottom ) ;
  2183.             if ( aWin == theWindows + WIN_MESSAGE )
  2184.                 r . top += SBARHEIGHT + 1 ;
  2185.             l = GrowWindow ( theWindow , theEvent -> where , & r ) ;
  2186.             SizeWindow ( theWindow , l & 0xffff , l >> 16 , FALSE ) ;
  2187.             SaveWindowSize ( theWindow ) ;
  2188.             SetPort ( theWindow ) ;
  2189.             InvalRect ( & ( theWindow -> portRect ) ) ;
  2190.             if ( aWin -> scrollBar ) {
  2191.                 InvalScrollBar ( aWin ) ;
  2192.             }
  2193.         } else {
  2194.             nhbell ( ) ;
  2195.         }
  2196.         break ;
  2197.  
  2198.     case inGoAway :
  2199.         WindowGoAway(theEvent, theWindow);
  2200.         break ;
  2201.  
  2202.     case inMenuBar :
  2203.         UpdateMenus ( ) ;
  2204.         DoMenu ( MenuSelect ( theEvent -> where ) ) ;
  2205.         break ;
  2206.  
  2207.     case inSysWindow :
  2208.         SystemClick( theEvent, theWindow ) ;
  2209.         break ;
  2210.  
  2211.     default :
  2212.         break ;
  2213.     }
  2214. }
  2215.  
  2216.  
  2217. void
  2218. HandleUpdate ( EventRecord * theEvent )
  2219. {
  2220.     WindowPtr theWindow = ( WindowPtr ) theEvent -> message ;
  2221.  
  2222.     BeginUpdate ( theWindow ) ;
  2223.     SetPort ( theWindow ) ;
  2224.     EraseRect ( & ( theWindow -> portRect ) ) ;
  2225.     GetNhWin ( theWindow ) -> updateFunc ( theEvent , theWindow ) ;
  2226.     EndUpdate ( theWindow ) ;
  2227. }
  2228.  
  2229.  
  2230. static void
  2231. DoOsEvt ( EventRecord * theEvent )
  2232. {
  2233.     WindowPtr wp ;
  2234.     short code ;
  2235.  
  2236.     if ( ( theEvent -> message & 0xff000000 ) == 0xfa000000 ) { /* Mouse Moved */
  2237.  
  2238.         code = FindWindow ( theEvent -> where , & wp ) ;
  2239.         if ( code != inContent ) {
  2240.  
  2241.             Rect r = { -1 , -1 , 2 , 2 } ;
  2242.  
  2243.             InitCursor ( ) ;
  2244.             OffsetRect ( & r , theEvent -> where . h , theEvent -> where . v ) ;
  2245.             RectRgn ( gMouseRgn , & r ) ;
  2246.  
  2247.         } else {
  2248.  
  2249.             NhWindow * nhw = GetNhWin ( wp ) ;
  2250.             if ( nhw ) {
  2251.                 nhw -> cursorFunc ( theEvent , wp , gMouseRgn ) ;
  2252.             }
  2253.         }
  2254.     } else {
  2255.  
  2256.         /* Suspend/resume */
  2257.         if ( ( ( theEvent -> message & osEvtMessageMask) >> 24 ) == suspendResumeMessage )
  2258.             kApplicInFront = ( theEvent -> message & resumeFlag );
  2259.     }
  2260. }
  2261.  
  2262.  
  2263. void
  2264. HandleEvent ( EventRecord * theEvent )
  2265. {
  2266.     switch ( theEvent -> what ) {
  2267.     case autoKey :
  2268.     case keyDown :
  2269.         HandleKey ( theEvent ) ;
  2270.         break ;
  2271.     case updateEvt :
  2272.         HandleUpdate ( theEvent ) ;
  2273.         break ;
  2274.     case mouseDown :
  2275.         HandleClick ( theEvent ) ;
  2276.         break ;
  2277.     case diskEvt :
  2278.         if ( ( theEvent -> message & 0xffff0000 ) != 0 ) {
  2279.  
  2280.             Point p = { 150 , 150 } ;
  2281.             ( void ) DIBadMount ( p , theEvent -> message ) ;
  2282.         }
  2283.         break ;
  2284.     case osEvt :
  2285.         DoOsEvt ( theEvent ) ;
  2286.         break ;
  2287.     default :
  2288.         if ( multi < 0 ) { // Get frozen, so stop repeating
  2289.             int ix;
  2290.             for ( ix = 0 ; ix < QUEUE_LEN ; ix ++ ) {
  2291.                 keyQueue [ ix ] = 0 ;
  2292.             }
  2293.             FlushEvents ( keyDownMask , 0 ) ;
  2294.         }
  2295.         break ;
  2296.     }
  2297. }
  2298.  
  2299.  
  2300. long doDawdle = 0L ;
  2301.  
  2302. void
  2303. WindowGoAway ( EventRecord * theEvent, WindowPtr theWindow )
  2304. {
  2305.     NhWindow * aWin = GetNhWin(theWindow);
  2306.  
  2307.     if ( ! theEvent || TrackGoAway ( theWindow , theEvent -> where ) ) {
  2308.         if ( aWin - theWindows == BASE_WINDOW && ! flags . window_inited ) {
  2309.             AddToKeyQueue ( '\033' , 1 ) ;
  2310.             return ;
  2311.         } else {
  2312.             HideWindow ( theWindow ) ;
  2313.         }
  2314.         if ( inSelect == WIN_ERR || aWin - theWindows != inSelect ) {
  2315.             destroy_nhwindow ( aWin - theWindows ) ;
  2316.         } else {
  2317.             AddToKeyQueue ( '\033' , 1 ) ;
  2318.         }
  2319.     }
  2320. }
  2321.  
  2322. void
  2323. DimMenuBar ( void )
  2324. {
  2325.     extern void AdjustMenus(short);
  2326.  
  2327.     AdjustMenus(1);
  2328. }
  2329.  
  2330.  
  2331. void
  2332. UndimMenuBar ( void )
  2333. {
  2334.     extern void AdjustMenus(short);
  2335.  
  2336.     AdjustMenus(0);
  2337. }
  2338.  
  2339. static int mBarDimmed = 0 ;
  2340.  
  2341. void
  2342. mac_get_nh_event( void )
  2343. {
  2344.     EventRecord anEvent ;
  2345.  
  2346.     if ( ( inSelect == WIN_ERR && flags . window_inited && ! in_topl_mode ( ) )
  2347.          == mBarDimmed )
  2348.         if ( mBarDimmed ) {
  2349.             UndimMenuBar ( ) ;
  2350.             mBarDimmed = 0 ;
  2351.         } else {
  2352.             DimMenuBar ( ) ;
  2353.             mBarDimmed = 1 ;
  2354.         }
  2355.     /*
  2356.      * We want to take care of keys in the buffer as fast as
  2357.      * possible
  2358.      */
  2359.     if ( keyQueue [ 0 ] ) {
  2360.         doDawdle = 0L ;
  2361.     }
  2362.     if ( asyDSC ) {
  2363.         SetPort ( asyDSC -> theWindow ) ;
  2364.         DrawScrollbar ( asyDSC , asyDSC -> theWindow ) ;
  2365.     }
  2366.     if ( kApplicInFront ) {
  2367.         AdjustMenus ( 0 ) ;
  2368.     }
  2369.     (void) WaitNextEvent ( -1 , & anEvent , doDawdle , gMouseRgn ) ;
  2370.     doDawdle = 0L ;
  2371. #if 0
  2372.     /* I don't want to make the tty cursor blinking. */
  2373.     if ( handle_tty_event ( _mt_window , & anEvent ) )    
  2374. #endif
  2375.         HandleEvent ( & anEvent ) ;
  2376.  
  2377.     if (top_line && theWindows) {
  2378.         WindowPeek win = (WindowPeek)theWindows[WIN_MESSAGE].theWindow;
  2379.         if (win && win->visible)
  2380.             TEIdle(top_line);
  2381.     }
  2382. }
  2383.  
  2384.  
  2385. int
  2386. GetFromKeyQueue ( void ) {
  2387. int ix , ret ;
  2388.  
  2389.     ret = keyQueue [ 0 ] ;
  2390.     for ( ix = 0 ; ix < QUEUE_LEN - 1 ; ix ++ ) {
  2391.         keyQueue [ ix ] = keyQueue [ ix + 1 ] ;
  2392.     }
  2393.     keyQueue [ ix ] = 0 ;
  2394.  
  2395.     return ret ;
  2396. }
  2397.  
  2398.  
  2399. int
  2400. mac_nhgetch( void ) {
  2401. int ch ;
  2402. NhWindow * nhw = flags . window_inited ? theWindows + WIN_MAP : (NhWindow *) nil ;
  2403.  
  2404.     if ( theWindows ) {
  2405.     NhWindow * aWin = theWindows + WIN_MESSAGE ;
  2406.  
  2407.         if ( WIN_MESSAGE > 0 ) {
  2408.             aWin -> last_more_lin = aWin -> lin ;
  2409.         }
  2410.     }
  2411.  
  2412.     wait_synch ( ) ;
  2413.  
  2414.     if ( ! keyQueue [ 0 ] ) {
  2415.         long total , contig ;
  2416.         static char warn = 0 ;
  2417.  
  2418.         PurgeSpace ( & total , & contig ) ;
  2419.         if ( contig < 25000L || total < 50000L ) {
  2420.             if ( ! warn ) {
  2421.                 pline ( "Low Memory!" ) ;
  2422.                 warn = 1 ;
  2423.             }
  2424.         } else {
  2425.             warn = 0 ;
  2426.         }
  2427.     }
  2428.  
  2429.     do {
  2430.         doDawdle = ( in_topl_mode() ? GetCaretTime ( ) : 120L ) ;
  2431.  
  2432.         if ( nhw ) {
  2433.             SetPort ( nhw -> theWindow ) ;
  2434.             if ( WaitMouseUp ( ) ) {
  2435.             unsigned long tick = TickCount ( ) ;
  2436.  
  2437.                 if ( tick >= gNextClickRepeat ) {
  2438.                 Point where ;
  2439.  
  2440.                     GetMouse ( & where ) ;
  2441.                     SetPt ( & clicked_pos , where . h / nhw -> charWidth ,
  2442.                                             where . v / nhw -> charHeight ) ;
  2443.                     gClickedToMove = TRUE ;
  2444.                     gNextClickRepeat = tick + * ( short * ) KeyRepThresh ;
  2445.                 }
  2446.                 if ( doDawdle > * ( short * ) KeyRepThresh ) {
  2447.                     doDawdle = * ( short * ) KeyRepThresh ;
  2448.                 }
  2449.             } else {
  2450.                 gNextClickRepeat = 0xffffffff ;
  2451.             }
  2452.         }
  2453.  
  2454.         get_nh_event ( ) ;
  2455.         ch = GetFromKeyQueue ( ) ;
  2456.     } while ( ! ch && ! gClickedToMove ) ;
  2457.  
  2458.     if ( ! gClickedToMove ) {
  2459.         ObscureCursor ( ) ;
  2460.     } else {
  2461.         gClickedToMove = 0 ;
  2462.     }
  2463.  
  2464. #ifdef THINK_C
  2465.     if (ch == '\r') ch = '\n';
  2466. #endif
  2467.  
  2468.     return ch ;
  2469. }
  2470.  
  2471.  
  2472. void
  2473. mac_delay_output( void )
  2474. {
  2475.     long destTicks = TickCount ( ) + 1 ;
  2476.  
  2477.     while ( TickCount ( ) < destTicks ) {
  2478.         wait_synch ( ) ;
  2479.     }
  2480. }
  2481.  
  2482.  
  2483. void
  2484. mac_wait_synch( void )
  2485. {
  2486.     get_nh_event ( ) ;
  2487. }
  2488.  
  2489.  
  2490. void
  2491. mac_mark_synch( void )
  2492. {
  2493.     get_nh_event ( ) ;
  2494. }
  2495.  
  2496.  
  2497. void
  2498. mac_cliparound ( int x , int y )
  2499. {
  2500.     /* TODO */
  2501.     if ( ! ( x * ( y + 1 ) ) ) {
  2502.         Debugger ( ) ;
  2503.     }
  2504. }
  2505.  
  2506.  
  2507. void
  2508. mac_raw_print ( const char * str )
  2509. {
  2510.     tty_raw_print(str);
  2511. }
  2512.  
  2513.  
  2514. void
  2515. mac_raw_print_bold ( const char * str )
  2516. {
  2517.     tty_raw_print_bold(str);
  2518. }
  2519.  
  2520.  
  2521. void
  2522. mac_exit_nhwindows ( const char * s )
  2523. {
  2524.     clear_screen ( ) ;
  2525.     tty_exit_nhwindows ( s ) ;
  2526.     destroy_nhwindow ( WIN_MESSAGE ) ;
  2527.     destroy_nhwindow ( WIN_INVEN ) ;
  2528. }
  2529.  
  2530.  
  2531. /*
  2532.  * Don't forget to decrease in_putstr before returning...
  2533.  */
  2534. void
  2535. mac_putstr ( winid win , int attr , const char * str )
  2536. {
  2537.     long len , slen ;
  2538.     NhWindow * aWin = & theWindows [ win ] ;
  2539.     int kind ;
  2540.     static char in_putstr = 0 ;
  2541.     Rect r ;
  2542.  
  2543.     if ( in_putstr > 3 ) {
  2544.         /* DebugStr ( ( ConstStr255Param ) "\pRecursion!" ) ; */
  2545.         return ;
  2546.     }
  2547.     if ( win < 0 || win >= NUM_MACWINDOWS ) {
  2548.         error ( "Invalid window %d (Max %d) in putstr." , win ,
  2549.             NUM_MACWINDOWS , attr ) ;
  2550.         return ;
  2551.     }
  2552.     if ( ! aWin -> theWindow ) {
  2553.         error ( "Unallocated window %d in putstr." , win ) ;
  2554.         return ;
  2555.     }
  2556.  
  2557.     if (aWin->theWindow == _mt_window) {
  2558.         tty_putstr(win, attr, str);
  2559.         return;
  2560.     }
  2561.  
  2562.     in_putstr ++ ;
  2563.     kind = ( ( WindowPeek ) ( aWin -> theWindow ) ) -> windowKind -
  2564.         WIN_BASE_KIND ;
  2565.     slen = strlen ( str ) ;
  2566.  
  2567.     {
  2568.         char * sr , * ds ;
  2569.  
  2570.         r = aWin->theWindow->portRect;
  2571.         if (win && win == WIN_MESSAGE) {
  2572.             r.right  -= SBARWIDTH  + 1;
  2573.             r.bottom -= SBARHEIGHT + 1;
  2574.             if ( aWin->last_more_lin < aWin->scrollPos )
  2575.                 aWin->last_more_lin = aWin->scrollPos;
  2576.             if ( flags.page_wait && aWin->last_more_lin <=
  2577.                  aWin->lin - (r.bottom - r.top) / aWin->charHeight )
  2578.                 display_nhwindow(win, TRUE);
  2579.         }
  2580.  
  2581.         /*
  2582.          * A "default" text window - uses TextBox
  2583.          * We just add the text, without attributes for now
  2584.          */
  2585.         len = GetHandleSize ( aWin -> windowText ) ;
  2586.         while ( aWin -> windowTextLen + slen + 1 > len ) {
  2587.             len = ( len > 2048 ) ? ( len + 2048 ) : ( len * 2 ) ;
  2588.             SetHandleSize ( aWin -> windowText , len ) ;
  2589.             if ( MemError ( ) ) {
  2590.                 error ( "SetHandleSize (putstr)" ) ;
  2591.                 aWin -> windowTextLen = 0L ;
  2592.                 aWin -> save_lin = 0 ;
  2593.                 aWin -> lin = 0 ;
  2594.             }
  2595.         }
  2596.     
  2597.         len = aWin -> windowTextLen ;
  2598.         sr = (char *)str ;
  2599.         ds = * ( aWin -> windowText ) + len ;
  2600.         while ( * sr ) {
  2601.             if ( * sr == CHAR_LF )
  2602.                 * ds = CHAR_CR ;
  2603.             else
  2604.                 * ds = * sr ;
  2605.             if ( * ds == CHAR_CR && kind != NHW_MENU ) {
  2606.                 aWin -> lin ++ ;
  2607.             }
  2608.             sr ++ ;
  2609.             ds ++ ;
  2610.         }
  2611.  
  2612.         ( * ( aWin -> windowText ) ) [ len + slen ] = CHAR_CR ;
  2613.         aWin -> windowTextLen += slen + 1 ;
  2614.         aWin -> lin ++ ;
  2615.     
  2616.         SetPort ( aWin -> theWindow ) ;
  2617.         InvalRect ( & r ) ;
  2618.         aWin -> clear = 0 ;
  2619.         if ( kind == NHW_MESSAGE ) {
  2620.             short min = aWin->lin - (r.bottom - r.top) / aWin->charHeight;
  2621.             if (aWin->scrollPos < min) {
  2622.                 aWin->scrollPos = min;
  2623.                 SetCtlMax  (aWin->scrollBar, aWin->lin);
  2624.                 SetCtlValue(aWin->scrollBar, min);
  2625.             }
  2626.         }
  2627.         if ( aWin -> scrollBar ) {
  2628.             InvalScrollBar ( aWin ) ;
  2629.         }
  2630.     }
  2631.     in_putstr -- ;
  2632. }
  2633.  
  2634.  
  2635. void
  2636. mac_curs ( winid win , int x , int y )
  2637. {
  2638.     NhWindow * aWin = & theWindows [ win ] ;
  2639.     int kind = ( ( WindowPeek ) ( aWin -> theWindow ) ) -> windowKind -
  2640.         WIN_BASE_KIND ;
  2641.  
  2642.     if (aWin->theWindow == _mt_window) {
  2643.         tty_curs(win, x, y);
  2644.         return;
  2645.     }
  2646.  
  2647.     SetPort  ( aWin -> theWindow ) ;
  2648.     MoveTo ( x * aWin -> charWidth , ( y + 1 ) * aWin -> charHeight -
  2649.         aWin -> leading ) ;
  2650.     SetPt ( & ( aWin -> cursor ) , x , y ) ;
  2651. }
  2652.  
  2653.  
  2654. void
  2655. mac_print_glyph ( winid window , XCHAR_P x , XCHAR_P y , int glyph )
  2656. {
  2657.     if (theWindows[window].theWindow != _mt_window)
  2658.         Debugger();
  2659.     tty_print_glyph(window, x, y, glyph);
  2660. }
  2661.  
  2662.  
  2663. int
  2664. mac_nh_poskey ( int * a , int * b , int * c )
  2665. {
  2666.     int ch = nhgetch();
  2667.     *a = clicked_pos.h;
  2668.     *b = clicked_pos.v;
  2669.     *c = clicked_mod;
  2670.     return ch;
  2671. }
  2672.  
  2673.  
  2674. void
  2675. mac_start_menu ( winid win )
  2676. {
  2677.     HideWindow ( theWindows [ win ] . theWindow ) ;
  2678.     clear_nhwindow ( win ) ;
  2679. }
  2680.  
  2681.  
  2682. void
  2683. mac_add_menu ( winid win , CHAR_P menuChar , int attr , const char * str )
  2684. {
  2685.     long addSize ;
  2686.     int newWid ;
  2687.     NhWindow * aWin = & theWindows [ win ] ;
  2688.  
  2689.     if ( ! str || aWin -> lin >= NUM_MENU_ITEMS )
  2690.         return ;
  2691.  
  2692.     SetPort ( aWin -> theWindow ) ;
  2693.     aWin -> itemChars [ aWin -> lin ] = menuChar ;
  2694.  
  2695.     addSize = strlen ( str ) ;
  2696.     newWid = TextWidth ( str , 0 , addSize ) ;
  2697.     if ( newWid > aWin -> wid )
  2698.         aWin -> wid = newWid ;
  2699.     putstr ( win , attr , str ) ;
  2700. }
  2701.  
  2702.  
  2703. /*
  2704.  * End a menu in this window, window must a type NHW_MENU.
  2705.  * ch is the value to return if the menu is canceled,
  2706.  * str is a list of cancel characters (values that may be input)
  2707.  * morestr is a prompt to display, rather than the default.
  2708.  * str and morestr might be ignored by some ports.
  2709.  */
  2710. void
  2711. mac_end_menu ( winid win , CHAR_P ch , const char * str , const char * morestr )
  2712. {
  2713.     unsigned char buf [ 256 ] ;
  2714.     int len ;
  2715.     NhWindow * aWin = & theWindows [ win ] ;
  2716.  
  2717.     strncpy ( aWin -> cancelStr , str , NUM_CANCEL_ITEMS ) ;
  2718.     aWin -> cancelStr [ NUM_CANCEL_ITEMS - 1 ] = 0 ;
  2719.     aWin -> cancelChar = ch ;
  2720.  
  2721.     buf [ 0 ] = 0 ;
  2722.     if ( morestr ) {
  2723.         strncpy ( (char *)& buf [ 1 ] , morestr , 255 ) ;
  2724.         len = strlen ( morestr ) ;
  2725.         if ( len > 255 )
  2726.             buf [ 0 ] = 255 ;
  2727.         else
  2728.             buf [ 0 ] = len ;
  2729.     }
  2730.     SetWTitle ( aWin -> theWindow , buf ) ;
  2731. }
  2732.  
  2733.  
  2734. char
  2735. mac_select_menu ( winid win )
  2736. {
  2737.     int c , l ;
  2738.     NhWindow * aWin = & theWindows [ win ] ;
  2739.     WindowPtr theWin = aWin -> theWindow ;
  2740.  
  2741.     inSelect = win ;
  2742.  
  2743.     adjust_window_pos ( aWin , theWin , aWin -> wid + ( SBARWIDTH + 2 ) ) ;
  2744.     SetPort ( theWin ) ;
  2745.     if ( aWin -> scrollBar ) {
  2746.         InvalScrollBar ( aWin ) ;
  2747.     }
  2748.     SelectWindow ( theWin ) ;
  2749.     ShowWindow ( theWin ) ;
  2750.     InvalRect ( & ( theWin -> portRect ) ) ;
  2751.  
  2752.     do {
  2753.         c = nhgetch ( ) ;
  2754.         for ( l = 0 ; l < aWin -> lin ; l ++ ) {
  2755.             if ( aWin -> itemChars [ l ] == c )
  2756.                 goto done ;
  2757.         }
  2758.         if ( ClosingWindowChar ( c ) ) {
  2759.             c = aWin -> cancelChar ;
  2760.         }
  2761.     } while ( ! strchr ( aWin -> cancelStr , c ) &&
  2762.         c != aWin -> cancelChar ) ;
  2763.  
  2764. done :
  2765.  
  2766.     HideWindow ( theWin ) ;
  2767.  
  2768.     inSelect = WIN_ERR ;
  2769.  
  2770.     return c ;
  2771. }
  2772.  
  2773.  
  2774. void
  2775. mac_display_file ( name, complain )
  2776. const char * name;
  2777. boolean    complain;
  2778. {
  2779.     long l ;
  2780.     short refNum ;
  2781.     Ptr buf ;
  2782.     int win ;
  2783.  
  2784.     if ( 0 > ( refNum = macopen ( name , O_RDONLY , TEXT_TYPE ) ) ) {
  2785.         if (complain) error ( "Cannot open file %s." , name ) ;
  2786.     } else {
  2787.         l = macseek ( refNum , 0 , SEEK_END ) ;
  2788.         ( void ) macseek ( refNum , 0 , 0L ) ;
  2789.         win = create_nhwindow ( NHW_TEXT ) ;
  2790.         if ( win == WIN_ERR ) {
  2791.             if (complain) error ( "Cannot make window." ) ;
  2792.             goto out ;
  2793.         }
  2794.         buf = NewPtr(l+1);
  2795.         if (buf)
  2796.             l = macread(refNum, buf, l);
  2797.         if (buf && l > 0) {
  2798.             buf[l] = '\0';
  2799.             putstr(win, 0, buf);
  2800.             display_nhwindow(win, FALSE);
  2801.         } else {
  2802.             HideWindow(theWindows[win].theWindow);
  2803.             destroy_nhwindow(win);
  2804.         }
  2805.         if (buf)
  2806.             DisposPtr(buf);
  2807. out :
  2808.         macclose ( refNum ) ;
  2809.     }
  2810. }
  2811.  
  2812.  
  2813. void
  2814. port_help ( )
  2815. {
  2816.     display_file ( PORT_HELP , TRUE ) ;
  2817. }
  2818.  
  2819.  
  2820. short frame_corner ;
  2821.  
  2822.  
  2823. static pascal void
  2824. FrameItem ( DialogPtr dlog , short item )
  2825. {
  2826.     short k ;
  2827.     Handle h ;
  2828.     Rect r ;
  2829.  
  2830.     GetDItem ( dlog , item , & k , & h , & r ) ;
  2831.     PenSize ( 3 , 3 ) ;
  2832.     FrameRoundRect ( & r , frame_corner , frame_corner ) ;
  2833.     PenNormal ( ) ;
  2834. }
  2835.  
  2836.  
  2837. void
  2838. SetFrameItem ( DialogPtr dlog , short frame , short item )
  2839. {
  2840.     Rect r , r2 ;
  2841.     short kind ;
  2842.     Handle h ;
  2843.  
  2844.     GetDItem ( dlog , item , & kind , & h , & r ) ;
  2845.     InsetRect ( & r , -4 , -4 ) ;
  2846.     r2 = r ;
  2847.     GetDItem ( dlog , frame , & kind , & h , & r ) ;
  2848.     SetDItem ( dlog , frame , kind , ( Handle ) FrameItem , & r2 ) ;
  2849.     frame_corner = 16 ;
  2850. }
  2851.  
  2852.  
  2853. //    Flash a button (for instance OK if you press enter)
  2854. //
  2855. void
  2856. FlashButton ( DialogPtr dlog , short item )
  2857. {
  2858.     short k ;
  2859.     Handle h ;
  2860.     Rect r ;
  2861.     long l ;
  2862.  
  2863.     GetDItem ( dlog , item , & k , & h , &  r ) ;
  2864.     if ( k == ctrlItem + btnCtrl ) {
  2865.         HiliteControl ( ( ControlHandle ) h , 1 ) ;
  2866.         Delay ( GetDblTime ( ) / 2 , & l ) ;
  2867.         HiliteControl ( ( ControlHandle ) h , 0 ) ;
  2868.     }
  2869. }
  2870.  
  2871.  
  2872. pascal Boolean
  2873. CharacterDialogFilter ( DialogPtr dp , EventRecord * ev , short * item )
  2874. {
  2875.     int ix ;
  2876.     Handle h ;
  2877.     Rect r ;
  2878.     short k ;
  2879.     Str255 s ;
  2880.     unsigned char com [ 2 ] ;
  2881.  
  2882.     if ( ev -> what == mouseDown ) {
  2883.  
  2884.         int code ;
  2885.         WindowPtr wp ;
  2886.         Rect r ;
  2887.  
  2888.         code = FindWindow ( ev -> where , & wp ) ;
  2889.         if ( wp != dp || code != inDrag ) {
  2890.     
  2891.             return 0 ;
  2892.         }
  2893.         r = ( * GetGrayRgn ( ) ) -> rgnBBox ;
  2894.         InsetRect ( & r , 3 , 3 ) ;
  2895.     
  2896.         DragWindow ( wp , ev -> where , & r ) ;
  2897.         SaveWindowPos ( wp ) ;
  2898.  
  2899.         ev -> what = nullEvent ;
  2900.         return 1 ;
  2901.     }
  2902.     if ( ev -> what != keyDown ) {
  2903.  
  2904.         return 0 ;
  2905.     }
  2906.     com [ 0 ] = 1 ;
  2907.     com [ 1 ] = ev -> message & 0xff ;
  2908.  
  2909.     if ( com [ 1 ] == 10 || com [ 1 ] == 13 || com [ 1 ] == 32 ||
  2910.         com [ 1 ] == 3 ) { // various "OK"
  2911.  
  2912.         * item = 1 ;
  2913.         FlashButton ( dp , 1 ) ;
  2914.         return 1 ;
  2915.     }
  2916.     if ( com [ 1 ] == 'Q' || com [ 1 ] == 'q' ||
  2917.          com [ 1 ] == 27 || ( ev -> message & 0xff00 == 0x3500 ) ) { // escape
  2918.  
  2919.         * item = 2 ;
  2920.         FlashButton ( dp , 2 ) ;
  2921.         return 1 ;
  2922.     }
  2923.     for ( ix = 3 ; ix ; ix ++ ) {
  2924.  
  2925.         h = ( Handle ) NULL ;
  2926.         k = 0 ;
  2927.         GetDItem ( dp , ix , & k , & h , & r ) ;
  2928.         if ( ! k || ! h ) {
  2929.  
  2930.             return 0 ;
  2931.         }
  2932.         if ( k == 6 ) { // Radio Button Item
  2933.  
  2934.             GetCTitle ( ( ControlHandle ) h , s ) ;
  2935.             s [ 0 ] = 1 ;
  2936.             if ( ! IUEqualString ( com , s ) ) {
  2937.  
  2938.                 * item = ix ;
  2939.                 return 1 ;
  2940.             }
  2941.         }
  2942.     }
  2943. /*NOTREACHED*/
  2944.     return 0 ;
  2945. }
  2946.  
  2947.  
  2948. void
  2949. mac_player_selection ( void )
  2950. {
  2951. /* see macmain.c:mac_askname() and macmenu.c:DialogAskName() */
  2952. }
  2953.  
  2954. void
  2955. mac_update_inventory ( void )
  2956. {
  2957. }
  2958.  
  2959.  
  2960. void
  2961. mac_suspend_nhwindows ( const char * foo)
  2962. {
  2963.     /*    Can't relly do that :-)        */
  2964. }
  2965.  
  2966.  
  2967. void
  2968. mac_resume_nhwindows ( void )
  2969. {
  2970.     /*    Can't relly do that :-)        */
  2971. }
  2972.  
  2973.  
  2974. int
  2975. try_key_queue ( char * bufp )
  2976. {
  2977.     if ( keyQueue [ 0 ] ) {
  2978.  
  2979.         int ix , flag = 0 ;
  2980.         for ( ix = 0 ; ix < QUEUE_LEN ; ix ++ ) {
  2981.  
  2982.             if ( ! flag ) {
  2983.  
  2984.                 if ( ! ( bufp [ ix ] = keyQueue [ ix ] ) ) {
  2985.  
  2986.                     flag = 1 ;
  2987.                 }
  2988.             }
  2989.             keyQueue [ ix ] = 0 ;
  2990.         }
  2991.         if ( ! flag ) {
  2992.  
  2993.             bufp [ ix ] = 0 ;
  2994.         }
  2995.         return 1 ;
  2996.     }
  2997.  
  2998.     return 0 ;
  2999. }
  3000.  
  3001. /* Interface definition, for windows.c */
  3002. struct window_procs mac_procs = {
  3003.     "mac",
  3004.     mac_init_nhwindows,
  3005.     mac_player_selection,
  3006.     mac_askname,
  3007.     mac_get_nh_event,
  3008.     mac_exit_nhwindows,
  3009.     mac_suspend_nhwindows,
  3010.     mac_resume_nhwindows,
  3011.     mac_create_nhwindow,
  3012.     mac_clear_nhwindow,
  3013.     mac_display_nhwindow,
  3014.     mac_destroy_nhwindow,
  3015.     mac_curs,
  3016.     mac_putstr,
  3017.     mac_display_file,
  3018.     mac_start_menu,
  3019.     mac_add_menu,
  3020.     mac_end_menu,
  3021.     mac_select_menu,
  3022.     mac_update_inventory,
  3023.     mac_mark_synch,
  3024.     mac_wait_synch,
  3025. #ifdef CLIPPING
  3026.     mac_cliparound,
  3027. #endif
  3028.     mac_print_glyph,
  3029.     mac_raw_print,
  3030.     mac_raw_print_bold,
  3031.     mac_nhgetch,
  3032.     mac_nh_poskey,
  3033.     mac_nhbell,
  3034.     mac_doprev_message,
  3035.     mac_yn_function,
  3036.     mac_getlin,
  3037. #ifdef COM_COMPL
  3038.     mac_get_ext_cmd,
  3039. #endif /* COM_COMPL */
  3040.     mac_number_pad,
  3041.     mac_delay_output,
  3042. #ifdef CHANGE_COLOR
  3043.     (void *) donull,
  3044.     (void *) donull,
  3045. #endif
  3046.     /* other defs that really should go away (they're tty specific) */
  3047.     0,    //    mac_start_screen,
  3048.     0, //    mac_end_screen,
  3049.     genl_outrip,
  3050. } ;
  3051.  
  3052. /*macwin.c*/
  3053.